home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / UPGRADE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  8.4 KB  |  365 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(struct pkgSet *psp, struct hash_table *ht, rpmdb db)
  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 void errorFunction(void)
  95. {
  96. }
  97.  
  98. static int findUpgradePackages(rpmdb db, int ugdbfd, struct hash_table *ht,
  99.                    char **resultArray, int *availPkgs)
  100. {
  101.     int pkgNum, skipThis;
  102.     Header h, installedHeader;
  103.     char *name, *version, *release;
  104.     dbiIndexSet matches;
  105.     int rc, i;
  106.     char **installedFiles, **availFiles;
  107.     int installedFileCount, availFileCount;
  108.  
  109.     lseek(ugdbfd, 0, SEEK_SET);
  110.  
  111.     pkgNum = 0;
  112.  
  113.     while ((h = headerRead(ugdbfd, HEADER_MAGIC_YES))) {
  114.     name = version = release = NULL;
  115.     headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  116.     headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
  117.     headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);
  118.     if (! (name && version && release)) {
  119.         /* bum header */
  120.         logMessage("Failed with bad header");
  121.         return(INST_ERROR);
  122.     }
  123.  
  124.     /* XXX - Need to do serial number stuff someday */
  125.     /*printf("Avail: %s-%s-%s\n", name, version, release);*/
  126.     rc = rpmdbFindPackage(db, name, &matches);
  127.  
  128.     if (rc == 0) {
  129.         skipThis = 0;
  130.         rpmErrorSetCallback(errorFunction);
  131.         for (i = 0; i < matches.count; i++) {
  132.         if (rpmEnsureOlder(db, name, version, release,
  133.                    matches.recs[i].recOffset)) {
  134.             /* already have a newer version installed */
  135.             /*printf("Already have newer version\n");*/
  136.             skipThis = 1;
  137.             break;
  138.         }
  139.         }
  140.         rpmErrorSetCallback(NULL);
  141.         if (! skipThis) {
  142.         /* no newer version installed */
  143.         /*printf("No newer version installed\n");*/
  144.         skipThis = 0;
  145.         }
  146.     } else {
  147.         skipThis = 1;
  148.         /*printf("Not installed\n");*/
  149.     }
  150.     
  151.     if (skipThis) {
  152.         /*printf("DO NOT INSTALL\n");*/
  153.     } else {
  154.         /*printf("UPGRADE\n");*/
  155.         if (!resultArray[pkgNum]) {
  156.         resultArray[pkgNum] = strdup(name);
  157.         }
  158.  
  159.         if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  160.               (void **) &availFiles, &availFileCount)) {
  161.         availFiles = NULL;
  162.         availFileCount = 0;
  163.         }
  164.  
  165.         for (i = 0; i < matches.count; i++) {
  166.         /* Compare the file lists */
  167.         installedHeader =
  168.             rpmdbGetRecord(db, matches.recs[i].recOffset);
  169.         if (!headerGetEntry(installedHeader, RPMTAG_FILENAMES, NULL,
  170.                   (void **) &installedFiles,
  171.                   &installedFileCount)) {
  172.             installedFiles = NULL;
  173.             installedFileCount = 0;
  174.         }
  175.  
  176.         compareFileList(availFileCount, availFiles,
  177.                 installedFileCount, installedFiles, ht);
  178.  
  179.         if (installedFiles) {
  180.             free(installedFiles);
  181.         }
  182.         headerFree(installedHeader);
  183.         }
  184.  
  185.         if (availFiles) {
  186.         free(availFiles);
  187.         }
  188.     }
  189.  
  190.     if (rc == 0) {
  191.         dbiFreeIndexRecord(matches);
  192.     }
  193.  
  194.     /*printf("\n\n");*/
  195.  
  196.  
  197.     headerFree(h);
  198.     pkgNum++;
  199.     }
  200.  
  201.     *availPkgs = pkgNum;
  202.     return 0;
  203. }
  204.  
  205. static int removeMovedFilesAlreadyHandled(int ugdbfd, struct hash_table *ht,
  206.                       char **resultArray)
  207. {
  208.     int pkgNum;
  209.     char *name;
  210.     int i;
  211.     Header h;
  212.     char **availFiles;
  213.     int availFileCount;
  214.     char *file;
  215.  
  216.     lseek(ugdbfd, 0, SEEK_SET);
  217.  
  218.     pkgNum = 0;
  219.     while ((h = headerRead(ugdbfd, HEADER_MAGIC_YES))) {
  220.     if (resultArray[pkgNum]) {
  221.         name = NULL;
  222.         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  223.  
  224.         if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  225.               (void **) &availFiles, &availFileCount)) {
  226.         availFiles = NULL;
  227.         availFileCount = 0;
  228.         }
  229.  
  230.         for (i = 0; i < availFileCount; i++) {
  231.         if ((file = htInTable(ht, availFiles[i]))) {
  232.             *file = '\0';
  233.             /*printf("File already in %s: %s\n", name, availFiles[i]);*/
  234.             if (!resultArray[pkgNum]) {
  235.             resultArray[pkgNum] = strdup(name);
  236.             }
  237.             break;
  238.         }
  239.         }
  240.         if (availFiles) {
  241.         free(availFiles);
  242.         }
  243.     }
  244.  
  245.     pkgNum++;
  246.     headerFree(h);
  247.     }
  248.  
  249.     return 0;
  250. }
  251.  
  252. static int findPackagesWithRelocatedFiles(int ugdbfd, struct hash_table *ht,
  253.                       char **resultArray)
  254. {
  255.     int pkgNum;
  256.     char *name;
  257.     int i;
  258.     Header h;
  259.     char **availFiles;
  260.     int availFileCount;
  261.     char *file;
  262.  
  263.     lseek(ugdbfd, 0, SEEK_SET);
  264.  
  265.     pkgNum = 0;
  266.     while ((h = headerRead(ugdbfd, HEADER_MAGIC_YES))) {
  267.     if (! resultArray[pkgNum]) {
  268.         name = NULL;
  269.         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
  270.  
  271.         availFiles = NULL;
  272.         availFileCount = 0;
  273.         if (headerGetEntry(h, RPMTAG_FILENAMES, NULL,
  274.              (void **) &availFiles, &availFileCount)) {
  275.         for (i = 0; i < availFileCount; i++) {
  276.             if ((file = htInTable(ht, availFiles[i]))) {
  277.             *file = '\0';
  278.             /*printf("Found file in %s: %s\n", name,
  279.                    availFiles[i]);*/
  280.             if (!resultArray[pkgNum]) {
  281.                 resultArray[pkgNum] = strdup(name);
  282.             }
  283.             break;
  284.             }
  285.         }
  286.         free(availFiles);
  287.         }
  288.     }
  289.  
  290.     pkgNum++;
  291.     headerFree(h);
  292.     }
  293.  
  294.     return 0;
  295. }
  296.  
  297. int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot,
  298.               char *ugdbName)
  299. {
  300.     int fd;
  301.     rpmdb db;
  302.     struct hash_table *hashTable;
  303.     char *installThisPackage[MAXPKGS];
  304.     int availPkgs, i, upgradeCount;
  305.     struct packageInfo **pack;
  306.     struct packageInfo key;
  307.     struct packageInfo *keyaddr = &key;
  308.  
  309.     if ((fd = open(ugdbName, O_RDONLY)) < 0) {
  310.     logMessage("failed opening %s", ugdbName);
  311.     return(INST_ERROR);
  312.     }
  313.  
  314.     rpmReadConfigFiles(NULL, NULL, NULL, 0);
  315.     if (rpmdbOpen(installRoot, &db, O_RDWR | O_CREAT, 0644)) {
  316.     close(fd);
  317.     logMessage("failed opening %s/var/lib/rpm/packages.rpm",
  318.              installRoot);
  319.     return(INST_ERROR);
  320.     }
  321.  
  322.     for (i = 0; i < MAXPKGS; i++) {
  323.     installThisPackage[i] = NULL;
  324.     }
  325.  
  326.     hashTable = htNewTable(1103);
  327.  
  328.     addLostFiles(psp, hashTable, db);
  329.     
  330.     if (findUpgradePackages(db, fd, hashTable, \
  331.                 installThisPackage, &availPkgs)) {
  332.     close(fd);
  333.     rpmdbClose(db);
  334.     return(INST_ERROR);
  335.     }
  336.     /*hash_stats(hashTable);*/
  337.  
  338.     removeMovedFilesAlreadyHandled(fd, hashTable, installThisPackage);
  339.  
  340.     findPackagesWithRelocatedFiles(fd, hashTable, installThisPackage);
  341.  
  342.     htFreeHashTable(hashTable);
  343.     
  344.     /*printMemStats("Done");*/
  345.  
  346.     rpmdbClose(db);
  347.     close(fd);
  348.  
  349.     upgradeCount = 0;
  350.     for (i = 0; i < MAXPKGS; i++) {
  351.     if (installThisPackage[i]) {
  352.         key.name = installThisPackage[i];
  353.         pack = bsearch(&keyaddr, psp->packages, psp->numPackages,
  354.                sizeof(*psp->packages), (void *)pkgCompare);
  355.         (*pack)->selected = 1;
  356.         free(installThisPackage[i]);
  357.         upgradeCount++;
  358.     }
  359.     }
  360.  
  361.     logMessage("ugFindUpgradePackages() marked %d packages", upgradeCount);
  362.  
  363.     return 0;
  364. }
  365.