1) changed doInstall() and doUninstall() calls to pass all of the arguments
authorewt <devnull@localhost>
Mon, 10 Jun 1996 17:41:24 +0000 (17:41 +0000)
committerewt <devnull@localhost>
Mon, 10 Jun 1996 17:41:24 +0000 (17:41 +0000)
   at once
2) added dependency checking

CVS patchset: 631
CVS date: 1996/06/10 17:41:24

install.c
install.h

index 7b2f1c0..213b68f 100644 (file)
--- a/install.c
+++ b/install.c
@@ -1,12 +1,14 @@
 #include <alloca.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "ftp.h"
 #include "install.h"
 #include "lib/rpmlib.h"
+#include "lib/package.h"
 #include "messages.h"
 #include "query.h"
 
@@ -14,7 +16,7 @@ static int hashesPrinted = 0;
 
 static void printHash(const unsigned long amount, const unsigned long total);
 static void printPercent(const unsigned long amount, const unsigned long total);
-static int getFtpURL(char * prefix, char * hostAndFile);
+static int getFtpURL(char * hostAndFile, char * dest);
 
 static void printHash(const unsigned long amount, const unsigned long total) {
     int hashesNeeded;
@@ -41,20 +43,16 @@ static void printPercent(const unsigned long amount, const unsigned long total)
     fflush(stdout);
 }
 
-int doInstall(char * prefix, char * arg, int installFlags, int interfaceFlags) {
-    rpmdb db;
-    int fd;
-    int mode, rc;
+static int installPackages(char * prefix, char ** packages, 
+                           int numPackages, int installFlags, 
+                           int interfaceFlags, rpmdb db) {
+    int i, fd;
+    int numFailed = 0;
+    char ** filename;
+    char * printFormat = NULL;
     char * chptr;
+    int rc;
     notifyFunction fn;
-    char * printFormat = NULL;
-
-    hashesPrinted = 0;
-
-    if (installFlags & INSTALL_TEST) 
-       mode = O_RDONLY;
-    else
-       mode = O_RDWR;
 
     if (interfaceFlags & RPMINSTALL_PERCENT)
        fn = printPercent;
@@ -62,71 +60,225 @@ int doInstall(char * prefix, char * arg, int installFlags, int interfaceFlags) {
        fn = printHash;
     else
        fn = NULL;
-       
-    if (rpmdbOpen(prefix, &db, mode | O_CREAT, 0644)) {
-       fprintf(stderr, "error: cannot open %s/var/lib/rpm/packages.rpm\n", 
-                   prefix);
-       exit(1);
+
+    for (i = 0, filename = packages; i < numPackages; i++, filename++) {
+       if (!*filename) continue;
+
+       fd = open(*filename, O_RDONLY);
+       if (fd < 0) {
+           fprintf(stderr, "error: cannot open %s\n", *filename);
+           numFailed++;
+           *filename = NULL;
+       }
+
+       if (interfaceFlags & RPMINSTALL_PERCENT) 
+           printFormat = "%%f %s:%s:%s\n";
+       else if (isVerbose() && (interfaceFlags & RPMINSTALL_HASH)) {
+           chptr = strrchr(*filename, '/');
+           if (!chptr)
+               chptr = *filename;
+           else
+               chptr++;
+
+           printFormat = "%-28s";
+       } else if (isVerbose())
+           printf("Installing %s\n", *filename);
+
+       if (db) {
+           rc = rpmInstallPackage(prefix, db, fd, installFlags, fn, 
+                                  printFormat);
+       } else {
+           if (installFlags &= INSTALL_TEST) {
+               message(MESS_DEBUG, "stopping source install as we're "
+                       "just testing\n");
+               rc = 0;
+           } else
+               rc = rpmInstallSourcePackage(prefix, fd, NULL);
+       } 
+
+       if (rc == 1) {
+           fprintf(stderr, "error: %s does not appear to be a RPM package\n", 
+                       *filename);
+       }
+           
+       if (rc) {
+           fprintf(stderr, "error: %s cannot be installed\n", *filename);
+           numFailed++;
+       }
+
+       close(fd);
     }
 
-    message(MESS_DEBUG, "installing %s\n", arg);
+    return numFailed;
+}
+
+int doInstall(char * prefix, char ** argv, int installFlags, 
+             int interfaceFlags) {
+    rpmdb db;
+    int fd, i;
+    int mode, rc;
+    char ** packages, ** tmpPackages;
+    char ** filename;
+    int numPackages;
+    int numTmpPackages = 0, numBinaryPackages = 0, numSourcePackages = 0;
+    int numFailed = 0;
+    Header * binaryHeaders;
+    int isSource;
+    int tmpnum = 0;
+    rpmDependencies rpmdep;
+    struct rpmDependencyConflict * conflicts;
+    int numConflicts;
+    int stopInstall = 0;
+
+    if (installFlags & INSTALL_TEST) 
+       mode = O_RDONLY;
+    else
+       mode = O_RDWR;
 
-    if (!strncmp(arg, "ftp://", 6)) {
-       if (isVerbose()) {
-           printf("Retrieving %s\n", arg);
+    message(MESS_DEBUG, "counting packages to install\n");
+    for (filename = argv, numPackages = 0; *filename; filename++, numPackages++)
+       ;
+
+    message(MESS_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));
+       
+    message(MESS_DEBUG, "looking for packages to download\n");
+    for (filename = argv, i = 0; *filename; filename++) {
+       if (!strncmp(*filename, "ftp://", 6)) {
+           if (isVerbose()) {
+               printf("Retrieving %s\n", *filename);
+           }
+           packages[i] = alloca(strlen(*filename) + 30 + strlen(prefix));
+           sprintf(packages[i], "%s/var/tmp/rpm-ftp-%d-%d.tmp", prefix, 
+                   tmpnum++, getpid());
+           message(MESS_DEBUG, "getting %s as %s\n", *filename, packages[i]);
+           fd = getFtpURL(*filename + 6, packages[i]);
+           if (fd < 0) {
+               fprintf(stderr, "error: skipping %s - ftp failed - %s\n", 
+                       *filename, ftpStrerror(fd));
+               numFailed++;
+           } else {
+               tmpPackages[numTmpPackages++] = packages[i];
+               i++;
+           }
+       } else {
+           packages[i++] = *filename;
        }
-       fd = getFtpURL(prefix, arg + 6);
+    }
+
+    message(MESS_DEBUG, "retrieved %d packages\n", numTmpPackages);
+
+    message(MESS_DEBUG, "finding source and binary packages\n");
+    for (filename = packages; *filename; filename++) {
+       fd = open(*filename, O_RDONLY);
        if (fd < 0) {
-           fprintf(stderr, "error: ftp of %s failed - %s\n", arg,
-                       ftpStrerror(fd));
-           return 1;
+           fprintf(stderr, "error: cannot open %s\n", *filename);
+           numFailed++;
+           *filename = NULL;
        }
-    } else {
-       fd = open(arg, O_RDONLY);
-       if (fd < 0) {
-           rpmdbClose(db);
-           fprintf(stderr, "error: cannot open %s\n", arg);
-           return 1;
+
+       rc = pkgReadHeader(fd, &binaryHeaders[numBinaryPackages], &isSource);
+
+       close(fd);
+       
+       if (rc == 1) {
+           fprintf(stderr, "error: %s does not appear to be a RPM package\n", 
+                       *filename);
+       }
+           
+       if (rc) {
+           fprintf(stderr, "error: %s cannot be installed\n", *filename);
+           numFailed++;
+           *filename = NULL;
+       } else if (isSource) {
+           freeHeader(binaryHeaders[numBinaryPackages]);
+           numSourcePackages++;
+       } else {
+           numBinaryPackages++;
        }
     }
 
-    if (interfaceFlags & RPMINSTALL_PERCENT) 
-       printFormat = "%%f %s:%s:%s\n";
-    else if (isVerbose() && (interfaceFlags & RPMINSTALL_HASH)) {
-       chptr = strrchr(arg, '/');
-       if (!chptr)
-           chptr = arg;
-       else
-           chptr++;
-
-       printFormat = "%-28s";
-    } else if (isVerbose())
-       printf("Installing %s\n", arg);
+    message(MESS_DEBUG, "found %d source and %d binary packages\n", 
+               numSourcePackages, numBinaryPackages);
 
-    rc = rpmInstallPackage(prefix, db, fd, installFlags, fn, printFormat);
-    if (rc == 1) {
-       fprintf(stderr, "error: %s does not appear to be a RPM package\n", arg);
+    if (numBinaryPackages) {
+       message(MESS_DEBUG, "opening database mode: 0%o\n", mode | O_CREAT);
+       if (rpmdbOpen(prefix, &db, mode | O_CREAT, 0644)) {
+           fprintf(stderr, "error: cannot open %s/var/lib/rpm/packages.rpm\n", 
+                       prefix);
+           exit(1);
+       }
+
+       if (!(interfaceFlags & RPMINSTALL_NODEPS)) {
+           rpmdep = rpmdepDependencies(db);
+           for (i = 0; i < numBinaryPackages; i++)
+               rpmdepAddPackage(rpmdep, binaryHeaders[i]);
+
+           if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) {
+               numFailed = numPackages;
+               stopInstall = 1;
+           }
+
+           if (!stopInstall && conflicts) {
+               fprintf(stderr, "failed dependencies:\n");
+               for (i = 0; i < numConflicts; i++) {
+                   fprintf(stderr, "\t%s is needed by %s-%s-%s\n",
+                           conflicts[i].needsName, conflicts[i].byName,
+                           conflicts[i].byVersion, conflicts[i].byRelease);
+               }
+               
+               free(conflicts);
+               numFailed = numPackages;
+               stopInstall = 1;
+           }
+       }
     }
-       
-    if (rc) {
-       fprintf(stderr, "error: %s cannot be installed\n", arg);
+    else
+       db = NULL;
+
+    if (!stopInstall) {
+       hashesPrinted = 0;
+       message(MESS_DEBUG, "installing binary packages\n");
+       numFailed += installPackages(prefix, packages, numPackages, 
+                                    installFlags, interfaceFlags, db);
     }
 
-    close(fd);
-    rpmdbClose(db);
+    for (i = 0; i < numTmpPackages; i++)
+       unlink(tmpPackages[i]);
 
-    return rc;
+    if (db) rpmdbClose(db);
+
+    return numFailed;
 }
 
-void doUninstall(char * prefix, char * arg, int flags, int uninstallFlags) {
+int doUninstall(char * prefix, char ** argv, int uninstallFlags,
+                int interfaceFlags) {
     rpmdb db;
     dbIndexSet matches;
-    int i;
+    int i, j;
     int mode;
     int rc;
     int count;
-
-    if (flags & UNINSTALL_TEST) 
+    int numPackages;
+    int * packageOffsets;
+    char ** arg;
+    int numFailed = 0;
+    rpmDependencies rpmdep;
+    struct rpmDependencyConflict * conflicts;
+    int numConflicts;
+    int stopUninstall = 0;
+
+    message(MESS_DEBUG, "counting packages to uninstall\n");
+    for (arg = argv, numPackages = 0; *arg; arg++, numPackages++)
+       ;
+    message(MESS_DEBUG, "found %d packages to uninstall\n", numPackages);
+
+    packageOffsets = alloca(sizeof(int *) * numPackages);
+
+    if (uninstallFlags & UNINSTALL_TEST) 
        mode = O_RDONLY;
     else
        mode = O_RDWR | O_EXCL;
@@ -135,35 +287,73 @@ void doUninstall(char * prefix, char * arg, int flags, int uninstallFlags) {
        fprintf(stderr, "cannot open %s/var/lib/rpm/packages.rpm\n", prefix);
        exit(1);
     }
-   
-    rc = findPackageByLabel(db, arg, &matches);
-    if (rc == 1) 
-       fprintf(stderr, "package %s is not installed\n", arg);
-    else if (rc == 2) 
-       fprintf(stderr, "error searching for package %s\n", arg);
-    else {
-       count = 0;
-       for (i = 0; i < matches.count; i++)
-           if (matches.recs[i].recOffset) count++;
-
-       if (count > 1) {
-           fprintf(stderr, "\"%s\" specifies multiple packages\n", arg);
-       }
-       else { 
-           for (i = 0; i < matches.count; i++) {
-               if (matches.recs[i].recOffset) {
-                   message(MESS_DEBUG, "uninstalling record number %d\n",
-                               matches.recs[i].recOffset);
-                   rpmRemovePackage(prefix, db, matches.recs[i].recOffset, 
-                                    0, flags & UNINSTALL_TEST);
+
+    j = 0;
+    for (arg = argv, numPackages = 0; *arg; arg++, numPackages++) {
+       rc = findPackageByLabel(db, *arg, &matches);
+       if (rc == 1) {
+           fprintf(stderr, "package %s is not installed\n", *arg);
+           numFailed++;
+       } else if (rc == 2) {
+           fprintf(stderr, "error searching for package %s\n", *arg);
+           numFailed++;
+       } else {
+           count = 0;
+           for (i = 0; i < matches.count; i++)
+               if (matches.recs[i].recOffset) count++;
+
+           if (count > 1) {
+               fprintf(stderr, "\"%s\" specifies multiple packages\n", *arg);
+               numFailed++;
+           }
+           else { 
+               for (i = 0; i < matches.count; i++) {
+                   if (matches.recs[i].recOffset) {
+                       packageOffsets[j++] = matches.recs[i].recOffset;
+                   }
                }
            }
+
+           freeDBIndexRecord(matches);
+       }
+    }
+    numPackages = j;
+
+    if (!(interfaceFlags & RPMUNINSTALL_NODEPS)) {
+       rpmdep = rpmdepDependencies(db);
+       for (i = 0; i < numPackages; i++)
+           rpmdepRemovePackage(rpmdep, packageOffsets[i]);
+
+       if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) {
+           numFailed = numPackages;
+           stopUninstall = 1;
+       }
+
+       if (!stopUninstall && conflicts) {
+           fprintf(stderr, "failed dependencies:\n");
+           for (i = 0; i < numConflicts; i++) {
+               fprintf(stderr, "\t%s is needed by %s-%s-%s\n",
+                       conflicts[i].needsName, conflicts[i].byName,
+                       conflicts[i].byVersion, conflicts[i].byRelease);
+           }
+           
+           free(conflicts);
+           numFailed += numPackages;
+           stopUninstall = 1;
        }
+    }
 
-       freeDBIndexRecord(matches);
+    if (!stopUninstall) {
+       for (i = 0; i < numPackages; i++) {
+           message(MESS_DEBUG, "uninstalling record number %d\n",
+                       packageOffsets[i]);
+           rpmRemovePackage(prefix, db, packageOffsets[i], 0, uninstallFlags);
+       }
     }
 
     rpmdbClose(db);
+
+    return numFailed;
 }
 
 int doSourceInstall(char * prefix, char * arg, char ** specFile) {
@@ -189,15 +379,13 @@ int doSourceInstall(char * prefix, char * arg, char ** specFile) {
     return rc;
 }
 
-static int getFtpURL(char * prefix, char * hostAndFile) {
+static int getFtpURL(char * hostAndFile, char * dest) {
     char * buf;
     char * chptr;
     int ftpconn;
     int fd;
     int rc;
    
-    char * tmp;
-
     message(MESS_DEBUG, "getting %s via anonymous ftp\n", hostAndFile);
 
     buf = alloca(strlen(hostAndFile) + 1);
@@ -214,18 +402,17 @@ static int getFtpURL(char * prefix, char * hostAndFile) {
 
     *chptr = '/';
 
-    tmp = alloca(strlen(prefix) + 60);
-    sprintf(tmp, "%s/var/tmp/rpm.ftp.%d", prefix, getpid());
-    fd = creat(tmp, 0600);
+    fd = creat(dest, 0600);
 
     if (fd < 0) {
-       unlink(tmp);
+       message(MESS_DEBUG, "failed to create %s\n", dest);
+       unlink(dest);
        ftpClose(ftpconn);
        return FTPERR_UNKNOWN;
     }
     
     if ((rc = ftpGetFile(ftpconn, chptr, fd))) {
-       unlink(tmp);
+       unlink(dest);
        close(fd);
        ftpClose(ftpconn);
        return rc;
@@ -233,10 +420,5 @@ static int getFtpURL(char * prefix, char * hostAndFile) {
 
     ftpClose(ftpconn);
 
-    close(fd);
-    fd = open(tmp, O_RDONLY);
-
-    unlink(tmp);
-
     return fd;
 }
index efc8edf..c8e9ab1 100644 (file)
--- a/install.h
+++ b/install.h
@@ -1,12 +1,17 @@
 #ifndef _H_INSTALL
 #define _H_INSTALL
 
-#define RPMINSTALL_PERCENT 1
-#define RPMINSTALL_HASH           2
+#define RPMINSTALL_PERCENT             (1 << 0)
+#define RPMINSTALL_HASH                        (1 << 1)
+#define RPMINSTALL_NODEPS              (1 << 2)
 
-int doInstall(char * prefix, char * arg, int installFlags, int interfaceFlags);
+#define RPMUNINSTALL_NODEPS            (1 << 0)
+
+int doInstall(char * prefix, char ** argv, int installFlags, 
+             int interfaceFlags);
 int doSourceInstall(char * prefix, char * arg, char ** specFile);
-void doUninstall(char * prefix, char * arg, int test, int uninstallFlags);
+int doUninstall(char * prefix, char ** argv, int uninstallFlags, 
+                int interfaceFlags);
 
 #endif