home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / install.c < prev    next >
C/C++ Source or Header  |  1997-09-17  |  12KB  |  465 lines

  1. #include "config.h"
  2.  
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8.  
  9. #if HAVE_ALLOCA_H
  10. # include <alloca.h>
  11. #endif
  12.  
  13. #include "miscfn.h"
  14. #include "install.h"
  15. #include "intl.h"
  16. #include "lib/rpmlib.h"
  17. #include "messages.h"
  18. #include "query.h"
  19. #include "url.h"
  20.  
  21. static int hashesPrinted = 0;
  22.  
  23. static void printHash(const unsigned long amount, const unsigned long total);
  24. static void printPercent(const unsigned long amount, const unsigned long total);
  25. static void printDepProblems(FILE * f, struct rpmDependencyConflict * conflicts,
  26.                  int numConflicts);
  27.  
  28. static void printHash(const unsigned long amount, const unsigned long total) {
  29.     int hashesNeeded;
  30.  
  31.     if (hashesPrinted != 50) {
  32.     hashesNeeded = 50 * (total ? (((float) amount) / total) : 1);
  33.     while (hashesNeeded > hashesPrinted) {
  34.         printf("#");
  35.         hashesPrinted++;
  36.     }
  37.     fflush(stdout);
  38.     hashesPrinted = hashesNeeded;
  39.  
  40.     if (hashesPrinted == 50)
  41.         printf("\n");
  42.     }
  43. }
  44.  
  45. static void printPercent(const unsigned long amount, const unsigned long total) 
  46. {
  47.     printf("%%%% %f\n", (total
  48.                         ? ((float) ((((float) amount) / total) * 100))
  49.                         : 100.0));
  50.     fflush(stdout);
  51. }
  52.  
  53. static int installPackages(char * rootdir, char ** packages, char * location,
  54.                 int numPackages, int installFlags, 
  55.                 int interfaceFlags, rpmdb db) {
  56.     int i, fd;
  57.     int numFailed = 0;
  58.     char ** filename;
  59.     char * printFormat = NULL;
  60.     char * chptr;
  61.     int rc;
  62.     rpmNotifyFunction fn;
  63.     char * netsharedPath = NULL;
  64.  
  65.     if (interfaceFlags & INSTALL_PERCENT)
  66.     fn = printPercent;
  67.     else if (interfaceFlags & INSTALL_HASH)
  68.     fn = printHash;
  69.     else
  70.     fn = NULL;
  71.  
  72.     netsharedPath = rpmGetVar(RPMVAR_NETSHAREDPATH);
  73.  
  74.     for (i = 0, filename = packages; i < numPackages; i++, filename++) {
  75.     if (!*filename) continue;
  76.  
  77.     hashesPrinted = 0;
  78.  
  79.     fd = open(*filename, O_RDONLY);
  80.     if (fd < 0) {
  81.         fprintf(stderr, _("error: cannot open file %s\n"), *filename);
  82.         numFailed++;
  83.         *filename = NULL;
  84.         continue;
  85.     } 
  86.  
  87.     if (interfaceFlags & INSTALL_PERCENT) 
  88.         printFormat = "%%f %s:%s:%s\n";
  89.     else if (rpmIsVerbose() && (interfaceFlags & INSTALL_HASH)) {
  90.         chptr = strrchr(*filename, '/');
  91.         if (!chptr)
  92.         chptr = *filename;
  93.         else
  94.         chptr++;
  95.  
  96.         printFormat = "%-28s";
  97.     } else if (rpmIsVerbose())
  98.         printf(_("Installing %s\n"), *filename);
  99.  
  100.     if (db) {
  101.         rc = rpmInstallPackage(rootdir, db, fd, location, installFlags, fn, 
  102.                    printFormat, netsharedPath);
  103.     } else {
  104.         if (installFlags &= RPMINSTALL_TEST) {
  105.         rpmMessage(RPMMESS_DEBUG, "stopping source install as we're "
  106.             "just testing\n");
  107.         rc = 0;
  108.         } else {
  109.         rc = rpmInstallSourcePackage(rootdir, fd, NULL, fn,
  110.                          printFormat);
  111.         }
  112.     } 
  113.  
  114.     if (rc == 1) {
  115.         fprintf(stderr, 
  116.             _("error: %s does not appear to be a RPM package\n"), 
  117.             *filename);
  118.     }
  119.         
  120.     if (rc) {
  121.         fprintf(stderr, _("error: %s cannot be installed\n"), *filename);
  122.         numFailed++;
  123.     }
  124.  
  125.     close(fd);
  126.     }
  127.  
  128.     return numFailed;
  129. }
  130.  
  131. int doInstall(char * rootdir, char ** argv, char * location, int installFlags, 
  132.           int interfaceFlags) {
  133.     rpmdb db;
  134.     int fd, i;
  135.     int mode, rc;
  136.     char ** packages, ** tmpPackages;
  137.     char ** filename;
  138.     int numPackages;
  139.     int numTmpPackages = 0, numBinaryPackages = 0, numSourcePackages = 0;
  140.     int numFailed = 0;
  141.     Header * binaryHeaders;
  142.     int isSource;
  143.     int tmpnum = 0;
  144.     rpmDependencies rpmdep;
  145.     struct rpmDependencyConflict * conflicts;
  146.     int numConflicts;
  147.     int stopInstall = 0;
  148.  
  149.     if (installFlags & RPMINSTALL_TEST) 
  150.     mode = O_RDONLY;
  151.     else
  152.     mode = O_RDWR | O_CREAT;
  153.  
  154.     rpmMessage(RPMMESS_DEBUG, "counting packages to install\n");
  155.     for (filename = argv, numPackages = 0; *filename; filename++, numPackages++)
  156.     ;
  157.  
  158.     rpmMessage(RPMMESS_DEBUG, "found %d packages\n", numPackages);
  159.     packages = alloca((numPackages + 1) * sizeof(char *));
  160.     packages[numPackages] = NULL;
  161.     tmpPackages = alloca((numPackages + 1) * sizeof(char *));
  162.     binaryHeaders = alloca((numPackages + 1) * sizeof(Header));
  163.     
  164.     rpmMessage(RPMMESS_DEBUG, "looking for packages to download\n");
  165.     for (filename = argv, i = 0; *filename; filename++) {
  166.     if (urlIsURL(*filename)) {
  167.         if (rpmIsVerbose()) {
  168.         printf(_("Retrieving %s\n"), *filename);
  169.         }
  170.         packages[i] = alloca(strlen(*filename) + 30 + strlen(rootdir));
  171.         sprintf(packages[i], "%s/var/tmp/rpm-ftp-%d-%d.tmp", rootdir, 
  172.             tmpnum++, (int) getpid());
  173.         rpmMessage(RPMMESS_DEBUG, 
  174.             "getting %s as %s\n", *filename, packages[i]);
  175.         fd = urlGetFile(*filename, packages[i]);
  176.         if (fd < 0) {
  177.         fprintf(stderr, 
  178.             _("error: skipping %s - transfer failed - %s\n"), 
  179.             *filename, ftpStrerror(fd));
  180.         numFailed++;
  181.         } else {
  182.         tmpPackages[numTmpPackages++] = packages[i];
  183.         i++;
  184.         }
  185.     } else {
  186.         packages[i++] = *filename;
  187.     }
  188.     }
  189.  
  190.     rpmMessage(RPMMESS_DEBUG, "retrieved %d packages\n", numTmpPackages);
  191.  
  192.     rpmMessage(RPMMESS_DEBUG, "finding source and binary packages\n");
  193.     for (filename = packages; *filename; filename++) {
  194.     fd = open(*filename, O_RDONLY);
  195.     if (fd < 0) {
  196.         fprintf(stderr, _("error: cannot open file %s\n"), *filename);
  197.         numFailed++;
  198.         *filename = NULL;
  199.         continue;
  200.     }
  201.  
  202.     rc = rpmReadPackageHeader(fd, &binaryHeaders[numBinaryPackages], 
  203.                     &isSource, NULL, NULL);
  204.  
  205.     close(fd);
  206.     
  207.     if (rc == 1) {
  208.         fprintf(stderr, 
  209.             _("error: %s does not appear to be a RPM package\n"), 
  210.             *filename);
  211.     }
  212.         
  213.     if (rc) {
  214.         fprintf(stderr, _("error: %s cannot be installed\n"), *filename);
  215.         numFailed++;
  216.         *filename = NULL;
  217.     } else if (isSource) {
  218.         /* the header will be NULL if this is a v1 source package */
  219.         if (binaryHeaders[numBinaryPackages])
  220.         headerFree(binaryHeaders[numBinaryPackages]);
  221.  
  222.         numSourcePackages++;
  223.     } else {
  224.         numBinaryPackages++;
  225.     }
  226.     }
  227.  
  228.     rpmMessage(RPMMESS_DEBUG, "found %d source and %d binary packages\n", 
  229.         numSourcePackages, numBinaryPackages);
  230.  
  231.     if (numBinaryPackages) {
  232.     rpmMessage(RPMMESS_DEBUG, "opening database mode: 0%o\n", mode);
  233.     if (rpmdbOpen(rootdir, &db, mode, 0644)) {
  234.         fprintf(stderr, "error: cannot open %s%s/packages.rpm\n", 
  235.             rpmGetVar(RPMVAR_DBPATH), rootdir);
  236.         exit(1);
  237.     }
  238.  
  239.     rpmdep = rpmdepDependencies(db);
  240.     for (i = 0; i < numBinaryPackages; i++)
  241.         if (installFlags & RPMINSTALL_UPGRADE)
  242.         rpmdepUpgradePackage(rpmdep, binaryHeaders[i],
  243.                      packages[i]);
  244.         else
  245.         rpmdepAddPackage(rpmdep, binaryHeaders[i], 
  246.                     packages[i]);
  247.  
  248.     if (!(interfaceFlags & INSTALL_NODEPS)) {
  249.         if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) {
  250.         numFailed = numPackages;
  251.         stopInstall = 1;
  252.         }
  253.  
  254.         if (!stopInstall && conflicts) {
  255.         fprintf(stderr, _("failed dependencies:\n"));
  256.         printDepProblems(stderr, conflicts, numConflicts);
  257.         rpmdepFreeConflicts(conflicts, numConflicts);
  258.         numFailed = numPackages;
  259.         stopInstall = 1;
  260.         }
  261.     }
  262.  
  263.     if (!(interfaceFlags & INSTALL_NOORDER)) {
  264.         if (rpmdepOrder(rpmdep, (void ***) &packages)) {
  265.         numFailed = numPackages;
  266.         stopInstall = 1;
  267.         }
  268.     }
  269.  
  270.     rpmdepDone(rpmdep);
  271.     }
  272.     else
  273.     db = NULL;
  274.  
  275.     if (!stopInstall) {
  276.     rpmMessage(RPMMESS_DEBUG, "installing binary packages\n");
  277.     numFailed += installPackages(rootdir, packages, location, numPackages, 
  278.                      installFlags, interfaceFlags, db);
  279.     }
  280.  
  281.     for (i = 0; i < numTmpPackages; i++)
  282.     unlink(tmpPackages[i]);
  283.  
  284.     for (i = 0; i < numBinaryPackages; i++) 
  285.     headerFree(binaryHeaders[i]);
  286.  
  287.     if (db) rpmdbClose(db);
  288.  
  289.     return numFailed;
  290. }
  291.  
  292. int doUninstall(char * rootdir, char ** argv, int uninstallFlags,
  293.          int interfaceFlags) {
  294.     rpmdb db;
  295.     dbiIndexSet matches;
  296.     int i, j;
  297.     int mode;
  298.     int rc;
  299.     int count;
  300.     int numPackages, packageOffsetsAlloced;
  301.     int * packageOffsets;
  302.     char ** arg;
  303.     int numFailed = 0;
  304.     rpmDependencies rpmdep;
  305.     struct rpmDependencyConflict * conflicts;
  306.     int numConflicts;
  307.     int stopUninstall = 0;
  308.  
  309.     rpmMessage(RPMMESS_DEBUG, "counting packages to uninstall\n");
  310.     for (arg = argv, numPackages = 0; *arg; arg++, numPackages++)
  311.     ;
  312.  
  313.     packageOffsetsAlloced = numPackages;
  314.     packageOffsets = malloc(sizeof(int *) * packageOffsetsAlloced);
  315.  
  316.     if (uninstallFlags & RPMUNINSTALL_TEST) 
  317.     mode = O_RDONLY;
  318.     else
  319.     mode = O_RDWR | O_EXCL;
  320.     
  321.     if (rpmdbOpen(rootdir, &db, mode, 0644)) {
  322.     fprintf(stderr, _("cannot open %s%s/packages.rpm\n"), 
  323.         rpmGetVar(RPMVAR_DBPATH), rootdir);
  324.     exit(1);
  325.     }
  326.  
  327.     j = 0;
  328.     numPackages = 0;
  329.     for (arg = argv; *arg; arg++) {
  330.     rc = rpmdbFindByLabel(db, *arg, &matches);
  331.     if (rc == 1) {
  332.         fprintf(stderr, _("package %s is not installed\n"), *arg);
  333.         numFailed++;
  334.     } else if (rc == 2) {
  335.         fprintf(stderr, _("error searching for package %s\n"), *arg);
  336.         numFailed++;
  337.     } else {
  338.         count = 0;
  339.         for (i = 0; i < matches.count; i++)
  340.         if (matches.recs[i].recOffset) count++;
  341.  
  342.         if (count > 1 && !(interfaceFlags & UNINSTALL_ALLMATCHES)) {
  343.         fprintf(stderr, _("\"%s\" specifies multiple packages\n"), 
  344.             *arg);
  345.         numFailed++;
  346.         }
  347.         else { 
  348.         numPackages += count;
  349.         if (numPackages > packageOffsetsAlloced) {
  350.             packageOffsetsAlloced = numPackages + 5;
  351.             packageOffsets = realloc(packageOffsets, 
  352.                 sizeof(int *) * packageOffsetsAlloced);
  353.         }
  354.         for (i = 0; i < matches.count; i++) {
  355.             if (matches.recs[i].recOffset) {
  356.             packageOffsets[j++] = matches.recs[i].recOffset;
  357.             }
  358.         }
  359.         }
  360.  
  361.         dbiFreeIndexRecord(matches);
  362.     }
  363.     }
  364.  
  365.     rpmMessage(RPMMESS_DEBUG, "found %d packages to uninstall\n", numPackages);
  366.  
  367.     if (!(interfaceFlags & UNINSTALL_NODEPS)) {
  368.     rpmdep = rpmdepDependencies(db);
  369.     for (i = 0; i < numPackages; i++)
  370.         rpmdepRemovePackage(rpmdep, packageOffsets[i]);
  371.  
  372.     if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) {
  373.         numFailed = numPackages;
  374.         stopUninstall = 1;
  375.     }
  376.  
  377.     rpmdepDone(rpmdep);
  378.  
  379.     if (!stopUninstall && conflicts) {
  380.         fprintf(stderr, _("removing these packages would break "
  381.                   "dependencies:\n"));
  382.         printDepProblems(stderr, conflicts, numConflicts);
  383.         rpmdepFreeConflicts(conflicts, numConflicts);
  384.         numFailed += numPackages;
  385.         stopUninstall = 1;
  386.     }
  387.     }
  388.  
  389.     if (!stopUninstall) {
  390.     for (i = 0; i < numPackages; i++) {
  391.         rpmMessage(RPMMESS_DEBUG, "uninstalling record number %d\n",
  392.             packageOffsets[i]);
  393.         if (rpmRemovePackage(rootdir, db, packageOffsets[i], 
  394.                  uninstallFlags))
  395.         numFailed++;
  396.     }
  397.     }
  398.  
  399.     rpmdbClose(db);
  400.  
  401.     free(packageOffsets);
  402.  
  403.     return numFailed;
  404. }
  405.  
  406. int doSourceInstall(char * rootdir, char * arg, char ** specFile) {
  407.     int fd;
  408.     int rc;
  409.  
  410.     fd = open(arg, O_RDONLY);
  411.     if (fd < 0) {
  412.     fprintf(stderr, _("error: cannot open %s\n"), arg);
  413.     return 1;
  414.     }
  415.  
  416.     if (rpmIsVerbose())
  417.     printf("Installing %s\n", arg);
  418.  
  419.     rc = rpmInstallSourcePackage(rootdir, fd, specFile, NULL, NULL);
  420.     if (rc == 1) {
  421.     fprintf(stderr, _("error: %s cannot be installed\n"), arg);
  422.     }
  423.  
  424.     close(fd);
  425.  
  426.     return rc;
  427. }
  428.  
  429. void printDepFlags(FILE * f, char * version, int flags) {
  430.     if (flags)
  431.     fprintf(f, " ");
  432.  
  433.     if (flags & RPMSENSE_LESS) 
  434.     fprintf(f, "<");
  435.     if (flags & RPMSENSE_GREATER)
  436.     fprintf(f, ">");
  437.     if (flags & RPMSENSE_EQUAL)
  438.     fprintf(f, "=");
  439.     if (flags & RPMSENSE_SERIAL)
  440.     fprintf(f, "S");
  441.  
  442.     if (flags)
  443.     fprintf(f, " %s", version);
  444. }
  445.  
  446. static void printDepProblems(FILE * f, struct rpmDependencyConflict * conflicts,
  447.                  int numConflicts) {
  448.     int i;
  449.  
  450.     for (i = 0; i < numConflicts; i++) {
  451.     fprintf(f, "\t%s", conflicts[i].needsName);
  452.     if (conflicts[i].needsFlags) {
  453.         printDepFlags(stderr, conflicts[i].needsVersion, 
  454.               conflicts[i].needsFlags);
  455.     }
  456.  
  457.     if (conflicts[i].sense == RPMDEP_SENSE_REQUIRES) 
  458.         fprintf(f, _(" is needed by %s-%s-%s\n"), conflicts[i].byName, 
  459.             conflicts[i].byVersion, conflicts[i].byRelease);
  460.     else
  461.         fprintf(f, _(" conflicts with %s-%s-%s\n"), conflicts[i].byName, 
  462.             conflicts[i].byVersion, conflicts[i].byRelease);
  463.     }
  464. }
  465.