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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <rpm/rpmlib.h>
  6. #include <rpm/header.h>
  7. #include <string.h>
  8.  
  9. #include "install.h"
  10. #include "log.h"
  11. #include "hash.h"
  12. #include "pkgs.h"
  13.  
  14. #define MAXPKGS 1024
  15.  
  16. #if 0
  17. static void printMemStats(char *mess)
  18. {
  19.     char buf[1024];
  20.     printf("%s\n", mess);
  21.     sprintf(buf, "cat /proc/%d/status | grep VmSize", getpid());
  22.     system(buf);
  23. }
  24. #endif
  25.  
  26. static void compareFileList(int availFileCount, char **availFiles,
  27.                 int installedFileCount, char **installedFiles,
  28.                 struct hash_table *ht)
  29. {
  30.     int installedX, availX, rc;
  31.     
  32.     availX = 0;
  33.     installedX = 0;
  34.     while (installedX < installedFileCount) {
  35.     if (availX == availFileCount) {
  36.         /* All the rest have moved */
  37.         /* printf("=> %s\n", installedFiles[installedX]); */
  38.         if (strncmp(installedFiles[installedX], "/etc/rc.d/", 10))
  39.         htAddToTable(ht, installedFiles[installedX]);
  40.         installedX++;
  41.     } else {
  42.         rc = strcmp(availFiles[availX], installedFiles[installedX]);
  43.         if (rc > 0) {
  44.         /* Avail > Installed -- file has moved */
  45.         /* printf("=> %s\n", installedFiles[installedX]); */
  46.         if (strncmp(installedFiles[installedX], "/etc/rc.d/", 10))
  47.             htAddToTable(ht, installedFiles[installedX]);
  48.         installedX++;
  49.         } else if (rc < 0) {
  50.         /* Avail < Installed -- avail has some new files */
  51.         availX++;
  52.         } else {
  53.         /* Files are equal -- file not moved */
  54.         availX++;
  55.         installedX++;
  56.         }
  57.     }
  58.     }
  59. }
  60.  
  61. static void addLostFiles( rpmdb db, struct pkgSet *psp, struct hash_table *ht)
  62. {
  63.     int num;
  64.     Header h;
  65.     char *name;
  66.     struct packageInfo **pack;
  67.     struct packageInfo key;
  68.     struct packageInfo *keyaddr = &key;
  69.     char **installedFiles;
  70.     int installedFileCount;
  71.  
  72.     num = rpmdbFirstRecNum(db);
  73.     while (num) {
  74.     h = rpmdbGetRecord(db, num);
  75.     headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  76.     key.name = name;
  77.     
  78.     pack = bsearch(&keyaddr, psp->packages, psp->numPackages,
  79.                sizeof(*psp->packages), (void *)pkgCompare);
  80.     if (!pack) {
  81.         if (headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  82.               (void **) &installedFiles, &installedFileCount)) {
  83.         compareFileList(0, NULL, installedFileCount,
  84.                 installedFiles, ht);
  85.         free(installedFiles);
  86.         }
  87.     }
  88.     
  89.     headerFree(h);
  90.     num = rpmdbNextRecNum(db, num);
  91.     }
  92. }
  93.  
  94. static int findPackagesWithObsoletes(rpmdb db, struct pkgSet *psp)
  95. {
  96.     dbiIndexSet matches;
  97.     int rc, count, obsoletesCount;
  98.     struct packageInfo **pip;
  99.     char **obsoletes;
  100.  
  101.     count = psp->numPackages;
  102.     pip = psp->packages;
  103.     while (count--) {
  104.     if ((*pip)->selected) {
  105.         pip++;
  106.         continue;
  107.     }
  108.  
  109.     if (headerGetEntry((*pip)->h, RPMTAG_OBSOLETES, NULL,
  110.                (void **) &obsoletes, &obsoletesCount)) {
  111.         while (obsoletesCount--) {
  112.         rc = rpmdbFindPackage(db, obsoletes[obsoletesCount], &matches);
  113.         if (!rc) {
  114.             if (matches.count) {
  115.             (*pip)->selected = 1;
  116.             dbiFreeIndexRecord(matches);
  117.             break;
  118.             }
  119.  
  120.             dbiFreeIndexRecord(matches);
  121.         }
  122.         }
  123.  
  124.         free(obsoletes);
  125.     }
  126.  
  127.     pip++;
  128.     }
  129.  
  130.     return 0;
  131. }
  132.  
  133. static void errorFunction(void)
  134. {
  135. }
  136.  
  137. static int findUpgradePackages(rpmdb db, struct pkgSet *psp,
  138.                    struct hash_table *ht)
  139. {
  140.     int skipThis;
  141.     Header h, installedHeader;
  142.     char *name, *version, *release;
  143.     dbiIndexSet matches;
  144.     int rc, i, count;
  145.     char **installedFiles, **availFiles;
  146.     int installedFileCount, availFileCount;
  147.     struct packageInfo **pip;
  148.  
  149.     count = psp->numPackages;
  150.     pip = psp->packages;
  151.     while (count--) {
  152.     h = (*pip)->h;
  153.     name = version = release = NULL;
  154.     headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  155.     headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
  156.     headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);
  157.     if (! (name && version && release)) {
  158.         /* bum header */
  159.         logMessage("Failed with bad header");
  160.         return(INST_ERROR);
  161.     }
  162.  
  163.     /* XXX - Need to do serial number stuff someday */
  164.     /*printf("Avail: %s-%s-%s\n", name, version, release);*/
  165.     rc = rpmdbFindPackage(db, name, &matches);
  166.  
  167.     if (rc == 0) {
  168.         skipThis = 0;
  169.         rpmErrorSetCallback(errorFunction);
  170.         for (i = 0; i < matches.count; i++) {
  171.         installedHeader =
  172.             rpmdbGetRecord(db, matches.recs[i].recOffset);
  173.         if (rpmVersionCompare(installedHeader, h) >= 0) {
  174.             /* already have a newer version installed */
  175.             /*printf("Already have newer version\n");*/
  176.             skipThis = 1;
  177.             break;
  178.         }
  179.         }
  180.         rpmErrorSetCallback(NULL);
  181.         if (! skipThis) {
  182.         /*printf("No newer version installed\n");*/
  183.         }
  184.     } else {
  185.         skipThis = 1;
  186.         /*printf("Not installed\n");*/
  187.     }
  188.     
  189.     if (skipThis) {
  190.         /*printf("DO NOT INSTALL\n");*/
  191.     } else {
  192.         /*printf("UPGRADE\n");*/
  193.         (*pip)->selected = 1;
  194.  
  195.         if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  196.               (void **) &availFiles, &availFileCount)) {
  197.         availFiles = NULL;
  198.         availFileCount = 0;
  199.         }
  200.  
  201.         for (i = 0; i < matches.count; i++) {
  202.         /* Compare the file lists */
  203.         installedHeader =
  204.             rpmdbGetRecord(db, matches.recs[i].recOffset);
  205.         if (!headerGetEntry(installedHeader, RPMTAG_FILENAMES, NULL,
  206.                   (void **) &installedFiles,
  207.                   &installedFileCount)) {
  208.             installedFiles = NULL;
  209.             installedFileCount = 0;
  210.         }
  211.  
  212.         compareFileList(availFileCount, availFiles,
  213.                 installedFileCount, installedFiles, ht);
  214.  
  215.         if (installedFiles) {
  216.             free(installedFiles);
  217.         }
  218.         headerFree(installedHeader);
  219.         }
  220.  
  221.         if (availFiles) {
  222.         free(availFiles);
  223.         }
  224.     }
  225.  
  226.     if (rc == 0) {
  227.         dbiFreeIndexRecord(matches);
  228.     }
  229.  
  230.     /*printf("\n\n");*/
  231.  
  232.     pip++;
  233.     }
  234.  
  235.     return 0;
  236. }
  237.  
  238. static int removeMovedFilesAlreadyHandled(struct pkgSet *psp,
  239.                       struct hash_table *ht)
  240. {
  241.     char *name;
  242.     int i, count;
  243.     Header h;
  244.     char **availFiles;
  245.     int availFileCount;
  246.     char *file;
  247.     struct packageInfo **pip;
  248.  
  249.     count = psp->numPackages;
  250.     pip = psp->packages;
  251.     while (count--) {
  252.     h = (*pip)->h;
  253.     if ((*pip)->selected) {
  254.         name = NULL;
  255.         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  256.  
  257.         if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  258.               (void **) &availFiles, &availFileCount)) {
  259.         availFiles = NULL;
  260.         availFileCount = 0;
  261.         }
  262.  
  263.         for (i = 0; i < availFileCount; i++) {
  264.         if ((file = htInTable(ht, availFiles[i]))) {
  265.             *file = '\0';
  266.             /*printf("File already in %s: %s\n", name, availFiles[i]);*/
  267.             break;
  268.         }
  269.         }
  270.         if (availFiles) {
  271.         free(availFiles);
  272.         }
  273.     }
  274.  
  275.     pip++;
  276.     }
  277.  
  278.     return 0;
  279. }
  280.  
  281. static int findPackagesWithRelocatedFiles(struct pkgSet *psp,
  282.                       struct hash_table *ht)
  283. {
  284.     char *name;
  285.     int i, count;
  286.     Header h;
  287.     char **availFiles;
  288.     int availFileCount;
  289.     char *file;
  290.     struct packageInfo **pip;
  291.  
  292.     count = psp->numPackages;
  293.     pip = psp->packages;
  294.     while (count--) {
  295.     h = (*pip)->h;
  296.     if (! (*pip)->selected) {
  297.         name = NULL;
  298.         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  299.  
  300.         availFiles = NULL;
  301.         availFileCount = 0;
  302.         if (headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  303.              (void **) &availFiles, &availFileCount)) {
  304.         for (i = 0; i < availFileCount; i++) {
  305.             if ((file = htInTable(ht, availFiles[i]))) {
  306.             *file = '\0';
  307.             /*printf("Found file in %s: %s\n", name,
  308.               availFiles[i]);*/
  309.             (*pip)->selected = 1;
  310.             break;
  311.             }
  312.         }
  313.         free(availFiles);
  314.         }
  315.     }
  316.  
  317.     pip++;
  318.     }
  319.  
  320.     return 0;
  321. }
  322.  
  323. static void printCount(struct pkgSet *psp)
  324. {
  325.     int i, upgradeCount;
  326.     struct packageInfo **pip;
  327.     
  328.     upgradeCount = 0;
  329.     pip = psp->packages;
  330.     i = psp->numPackages;
  331.     while (i--) {
  332.     if ((*pip)->selected) {
  333.         upgradeCount++;
  334.     }
  335.     pip++;
  336.     }
  337.     logMessage("marked %d packages for upgrade", upgradeCount);
  338. }
  339.  
  340. static int unmarkPackagesAlreadyInstalled(rpmdb db, struct pkgSet *psp)
  341. {
  342.     dbiIndexSet matches;
  343.     Header h, installedHeader;
  344.     char *name, *version, *release;
  345.     struct packageInfo **pip;
  346.     int count, rc, i;
  347.  
  348.     count = psp->numPackages;
  349.     pip = psp->packages;
  350.     while (count--) {
  351.     if ((*pip)->selected) {
  352.         h = (*pip)->h;
  353.         /* If this package is already installed, don't bother */
  354.         name = version = release = NULL;
  355.         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  356.         headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
  357.         headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);
  358.         if (! (name && version && release)) {
  359.         /* bum header */
  360.         logMessage("Failed with bad header");
  361.         return(INST_ERROR);
  362.         }
  363.         rc = rpmdbFindPackage(db, name, &matches);
  364.         if (rc == 0) {
  365.         rpmErrorSetCallback(errorFunction);
  366.         for (i = 0; i < matches.count; i++) {
  367.             installedHeader =
  368.             rpmdbGetRecord(db, matches.recs[i].recOffset);
  369.             if (rpmVersionCompare(installedHeader, h) >= 0) {
  370.             /* already have a newer version installed */
  371.             /*printf("Already have newer version\n");*/
  372.             (*pip)->selected = 0;
  373.             break;
  374.             }
  375.         }
  376.         rpmErrorSetCallback(NULL);
  377.         dbiFreeIndexRecord(matches);
  378.         }
  379.     }
  380.  
  381.     pip++;
  382.     }
  383.  
  384.     return 0;
  385. }
  386.         
  387.  
  388. int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot)
  389. {
  390.     rpmdb db;
  391.     struct hash_table *hashTable;
  392.  
  393.     logDebugMessage(("ugFindUpgradePackages() ..."));
  394.  
  395.     rpmReadConfigFiles(NULL, NULL, NULL, 0);
  396.  
  397.     if (rpmdbOpen(installRoot, &db, O_CREAT | O_RDWR, 0644)) {
  398.     logMessage("failed opening %s/var/lib/rpm/packages.rpm",
  399.              installRoot);
  400.     return(INST_ERROR);
  401.     }
  402.  
  403.     hashTable = htNewTable(1103);
  404.  
  405.     /* For all packages that are installed, if there is no package       */
  406.     /* available by that name, add the package's files to the hash table */
  407.     addLostFiles(db, psp, hashTable);
  408.     logDebugMessage(("added lost files"));
  409.     printCount(psp);
  410.     
  411.     /* Find packges that are new, and mark them in installThisPackage,  */
  412.     /* updating availPkgs with the count.  Also add files to the hash   */
  413.     /* table that do not exist in the new package - they may have moved */
  414.     if (findUpgradePackages(db, psp, hashTable)) {
  415.     rpmdbClose(db);
  416.     return(INST_ERROR);
  417.     }
  418.     logDebugMessage(("found basic packages to upgrade"));
  419.     printCount(psp);
  420.     /*hash_stats(hashTable);*/
  421.  
  422.     /* Remove any files that were added to the hash table that are in */
  423.     /* some other package marked for upgrade.                         */
  424.     removeMovedFilesAlreadyHandled(psp, hashTable);
  425.     logDebugMessage(("removed extra files which have moved"));
  426.     printCount(psp);
  427.  
  428.     findPackagesWithRelocatedFiles(psp, hashTable);
  429.     logDebugMessage(("found packages with relocated files"));
  430.     printCount(psp);
  431.  
  432.     findPackagesWithObsoletes(db, psp);
  433.     logDebugMessage(("found packages that obsolete installed packages"));
  434.     printCount(psp);
  435.     
  436.     unmarkPackagesAlreadyInstalled(db, psp);
  437.     logDebugMessage(("unmarked packages already installed"));
  438.     printCount(psp);
  439.     
  440.     htFreeHashTable(hashTable);
  441.     
  442.     /*printMemStats("Done");*/
  443.  
  444.     rpmdbClose(db);
  445.  
  446.     return 0;
  447. }
  448.