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