Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

python/upgrade.c

Go to the documentation of this file.
00001 
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <unistd.h>
00008 #include <fcntl.h>
00009 #include <string.h>
00010 
00011 #include <glob.h>       /* XXX rpmio.h */
00012 #include <dirent.h>     /* XXX rpmio.h */
00013 
00014 #include <rpmlib.h>
00015 
00016 #include "hash.h"
00017 #include "upgrade.h"
00018 
00019 #define MAXPKGS 1024
00020 
00021 #define USEDEBUG 0
00022 
00023 #define DEBUG(x) {   \
00024      if (USEDEBUG)   \
00025          printf x; \
00026      }
00027 
00028 #if 0
00029 static void printMemStats(char *mess)
00030 {
00031     char buf[1024];
00032     printf("%s\n", mess);
00033     sprintf(buf, "cat /proc/%d/status | grep VmSize", getpid());
00034     system(buf);
00035 }
00036 #endif
00037 
00038 int pkgCompare(void * first, void * second) {
00039     struct packageInfo ** a = first;
00040     struct packageInfo ** b = second;
00041 
00042     /* put packages w/o names at the end */
00043     if (!(*a)->name) return 1;
00044     if (!(*b)->name) return -1;
00045 
00046     return xstrcasecmp((*a)->name, (*b)->name);
00047 }
00048 
00049 
00050 /* Adds all files in the second file list which are not in the first
00051    file list to the hash table. */
00052 static void compareFileList(int availFileCount, char **availBaseNames,
00053                             char ** availDirNames, int * availDirIndexes,
00054                             int instFileCount, char **instBaseNames,
00055                             char ** instDirNames, int * instDirIndexes,
00056                             struct hash_table *ht)
00057 {
00058     int installedX, availX, rc;
00059     char * availDir, * availBase;
00060     char * instDir, * instBase;
00061     static int i = 0;
00062     
00063     availX = 0;
00064     installedX = 0;
00065     while (installedX < instFileCount) {
00066         instBase = instBaseNames[installedX];
00067         instDir = instDirNames[instDirIndexes[installedX]];
00068 
00069         if (availX == availFileCount) {
00070             /* All the rest have moved */
00071             DEBUG(("=> %d: %s%s\n", i++, instDir, instBase))
00072             if (strncmp(instDir, "/etc/rc.d/", 10))
00073                 htAddToTable(ht, instDir, instBase);
00074             installedX++;
00075         } else {
00076             availBase = availBaseNames[availX];
00077             availDir = availDirNames[availDirIndexes[availX]];
00078 
00079             rc = strcmp(availDir, instDir);
00080             if (!rc) 
00081                 rc = strcmp(availBase, instBase);
00082 
00083             if (rc > 0) {
00084                 /* Avail > Installed -- file has moved */
00085                 DEBUG(("=> %d: %s%s\n", i++, instDir, instBase))
00086                 if (strncmp(instDir, "/etc/rc.d/", 10))
00087                     htAddToTable(ht, instDir, instBase);
00088                 installedX++;
00089             } else if (rc < 0) {
00090                 /* Avail < Installed -- avail has some new files */
00091                 availX++;
00092             } else {
00093                 /* Files are equal -- file not moved */
00094                 availX++;
00095                 installedX++;
00096             }
00097         }
00098     }
00099 }
00100 
00101 static void addLostFiles(rpmdb db, struct pkgSet *psp, struct hash_table *ht)
00102 {
00103     char *name;
00104     struct packageInfo **pack;
00105     struct packageInfo key;
00106     struct packageInfo *keyaddr = &key;
00107     char **installedFiles;
00108     char **installedDirs;
00109     int_32 * installedDirIndexes;
00110     int installedFileCount;
00111     Header h = NULL;
00112     rpmdbMatchIterator mi;
00113 
00114     mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
00115     while ((h = rpmdbNextIterator(mi)) != NULL) {
00116 
00117         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
00118         if (name && !strcmp(name, "metroess")) {
00119             /* metro was removed from 5.1, but leave it if it's already
00120                installed */
00121             continue;
00122         }
00123         key.name = name;
00124         
00125         pack = bsearch(&keyaddr, psp->packages, psp->numPackages,
00126                        sizeof(*psp->packages), (void *)pkgCompare);
00127         if (!pack) {
00128             if (headerGetEntryMinMemory(h, RPMTAG_BASENAMES, NULL,
00129                           (const void **) &installedFiles, &installedFileCount)) {
00130                 headerGetEntryMinMemory(h, RPMTAG_DIRINDEXES, NULL,
00131                           (const void **) &installedDirIndexes, NULL);
00132                 headerGetEntryMinMemory(h, RPMTAG_DIRNAMES, NULL,
00133                           (const void **) &installedDirs, NULL);
00134 
00135                 compareFileList(0, NULL, NULL, NULL, installedFileCount,
00136                                 installedFiles, installedDirs,
00137                                 installedDirIndexes, ht);
00138 
00139                 free(installedFiles);
00140                 free(installedDirs);
00141             }
00142         }
00143     }
00144 
00145     rpmdbFreeIterator(mi);
00146 }
00147 
00148 static int findPackagesWithObsoletes(rpmdb db, struct pkgSet *psp)
00149 {
00150     int count, obsoletesCount;
00151     struct packageInfo **pip;
00152     char **obsoletes;
00153 
00154     count = psp->numPackages;
00155     pip = psp->packages;
00156     while (count--) {
00157         if ((*pip)->selected) {
00158             pip++;
00159             continue;
00160         }
00161 
00162         if (headerGetEntryMinMemory((*pip)->h, RPMTAG_OBSOLETENAME, NULL,
00163                        (const void **) &obsoletes, &obsoletesCount)) {
00164             while (obsoletesCount--) {
00165                 if (rpmdbCountPackages(db, obsoletes[obsoletesCount]) > 0) {
00166                     (*pip)->selected = 1;
00167                     break;
00168                 }
00169             }
00170 
00171             free(obsoletes);
00172         }
00173 
00174         pip++;
00175     }
00176 
00177     return 0;
00178 }
00179 
00180 static void errorFunction(void)
00181 {
00182 }
00183 
00184 static int findUpgradePackages(rpmdb db, struct pkgSet *psp,
00185                                struct hash_table *ht)
00186 {
00187     int skipThis;
00188     Header h, installedHeader;
00189     char *name;
00190     int count;
00191     char **installedFiles, **availFiles;
00192     char **installedDirs, ** availDirs;
00193     int_32 * installedDirIndexes, * availDirIndexes;
00194     int installedFileCount, availFileCount;
00195     struct packageInfo **pip;
00196 
00197     count = psp->numPackages;
00198     pip = psp->packages;
00199     while (count--) {
00200         h = (*pip)->h;
00201         name = NULL;
00202         headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
00203         if (!name) {
00204             /* bum header */
00205             /*logMessage("Failed with bad header");*/
00206             return(-1);
00207         }
00208         
00209         DEBUG (("Avail: %s\n", name));
00210 
00211     {   rpmdbMatchIterator mi;
00212 
00213         mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00214         skipThis = (mi ? 0 : 1);
00215         rpmErrorSetCallback(errorFunction);
00216         while((installedHeader = rpmdbNextIterator(mi)) != NULL) {
00217             if (rpmVersionCompare(installedHeader, h) >= 0) {
00218                 /* already have a newer version installed */
00219                 DEBUG (("Already have newer version\n"))
00220                 skipThis = 1;
00221                 break;
00222             }
00223         }
00224         rpmdbFreeIterator(mi);
00225         rpmErrorSetCallback(NULL);
00226         if (! skipThis) {
00227             DEBUG (("No newer version installed\n"))
00228         }
00229     }
00230         
00231         if (skipThis) {
00232             DEBUG (("DO NOT INSTALL\n"))
00233         } else {
00234             DEBUG (("UPGRADE\n"))
00235             (*pip)->selected = 1;
00236 
00237             if (!headerGetEntryMinMemory(h, RPMTAG_BASENAMES, NULL,
00238                           (const void **) &availFiles, &availFileCount)) {
00239                 availFiles = NULL;
00240                 availFileCount = 0;
00241             } else {
00242                 headerGetEntryMinMemory(h, RPMTAG_DIRNAMES, NULL,
00243                             (const void **) &availDirs, NULL);
00244                 headerGetEntryMinMemory(h, RPMTAG_DIRINDEXES, NULL,
00245                             (const void **) &availDirIndexes, NULL);
00246             }
00247 
00248         {   rpmdbMatchIterator mi;
00249             mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00250             while((installedHeader = rpmdbNextIterator(mi)) != NULL) {
00251                 if (headerGetEntryMinMemory(installedHeader, RPMTAG_BASENAMES, 
00252                               NULL, (const void **) &installedFiles,
00253                               &installedFileCount)) {
00254                     headerGetEntryMinMemory(installedHeader, RPMTAG_DIRNAMES, 
00255                                 NULL, (const void **) &installedDirs, NULL);
00256                     headerGetEntryMinMemory(installedHeader, RPMTAG_DIRINDEXES, 
00257                                 NULL, (const void **) &installedDirIndexes, NULL);
00258 
00259                     compareFileList(availFileCount, availFiles,
00260                                     availDirs, availDirIndexes,
00261                                     installedFileCount, installedFiles, 
00262                                     installedDirs, installedDirIndexes,
00263                                     ht);
00264 
00265                     free(installedFiles);
00266                     free(installedDirs);
00267                 }
00268             }
00269             rpmdbFreeIterator(mi);
00270         }
00271 
00272             if (availFiles) {
00273                 free(availFiles);
00274                 free(availDirs);
00275             }
00276         }
00277 
00278         DEBUG (("\n\n"))
00279 
00280         pip++;
00281     }
00282 
00283     return 0;
00284 }
00285 
00286 static int removeMovedFilesAlreadyHandled(struct pkgSet *psp,
00287                                           struct hash_table *ht)
00288 {
00289     char *name;
00290     int i, count;
00291     Header h;
00292     char **availFiles, ** availDirs;
00293     int_32 * availDirIndexes;
00294     int availFileCount;
00295     struct packageInfo **pip;
00296 
00297     count = psp->numPackages;
00298     pip = psp->packages;
00299     while (count--) {
00300         h = (*pip)->h;
00301         if ((*pip)->selected) {
00302             name = NULL;
00303             headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
00304 
00305             if (headerGetEntryMinMemory(h, RPMTAG_BASENAMES, NULL,
00306                           (const void **) &availFiles, &availFileCount)) {
00307 
00308                 headerGetEntryMinMemory(h, RPMTAG_DIRNAMES, NULL, 
00309                                (const void **) &availDirs, NULL);
00310                 headerGetEntryMinMemory(h, RPMTAG_DIRINDEXES, NULL, 
00311                                (const void **) &availDirIndexes, NULL);
00312 
00313                 for (i = 0; i < availFileCount; i++) {
00314                     if (htInTable(ht, availDirs[availDirIndexes[i]],
00315                                           availFiles[i])) {
00316                         htRemoveFromTable(ht, availDirs[availDirIndexes[i]],
00317                                           availFiles[i]);
00318                         DEBUG (("File already in %s: %s%s\n", name, 
00319                                 availDirs[availDirIndexes[i]], availFiles[i]))
00320                         break;
00321                     }
00322                 }
00323 
00324                 free(availFiles);
00325                 free(availDirs);
00326             }
00327         }
00328 
00329         pip++;
00330     }
00331 
00332     return 0;
00333 }
00334 
00335 static int findPackagesWithRelocatedFiles(struct pkgSet *psp,
00336                                           struct hash_table *ht)
00337 {
00338     char *name;
00339     int i, count;
00340     Header h;
00341     char **availFiles, **availDirs;
00342     int_32 * availDirIndexes;
00343     int availFileCount;
00344     struct packageInfo **pip;
00345     int_16 * availFileModes;
00346 
00347     count = psp->numPackages;
00348     pip = psp->packages;
00349     while (count--) {
00350         h = (*pip)->h;
00351         if (! (*pip)->selected) {
00352             name = NULL;
00353             headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
00354 
00355             if (headerGetEntry(h, RPMTAG_BASENAMES, NULL,
00356                          (void **) &availFiles, &availFileCount)) {
00357                 headerGetEntryMinMemory(h, RPMTAG_DIRNAMES, NULL,
00358                             (const void **) &availDirs, NULL);
00359                 headerGetEntryMinMemory(h, RPMTAG_DIRINDEXES, NULL,
00360                             (const void **) &availDirIndexes, NULL);
00361                 headerGetEntryMinMemory(h, RPMTAG_FILEMODES, NULL,
00362                             (const void **) &availFileModes, NULL);
00363 
00364                 for (i = 0; i < availFileCount; i++) {
00365                     if (S_ISDIR(availFileModes[i])) continue;
00366 
00367                     if (htInTable(ht, availDirs[availDirIndexes[i]], 
00368                                     availFiles[i])) {
00369                         htRemoveFromTable(ht, availDirs[availDirIndexes[i]],
00370                                           availFiles[i]);
00371                         DEBUG (("Found file in %s: %s%s\n", name,
00372                                 availDirs[availDirIndexes[i]], availFiles[i]))
00373                         (*pip)->selected = 1;
00374                     }
00375                 }
00376                 free(availFiles);
00377                 free(availDirs);
00378             }
00379         }
00380 
00381         pip++;
00382     }
00383 
00384     return 0;
00385 }
00386 
00387 /*
00388 static void printCount(struct pkgSet *psp)
00389 {
00390     int i, upgradeCount;
00391     struct packageInfo *pip;
00392     
00393     upgradeCount = 0;
00394     pip = psp->packages;
00395     i = psp->numPackages;
00396     while (i--) {
00397         if (pip->selected) {
00398             upgradeCount++;
00399         }
00400         pip++;
00401     }
00402     logMessage("marked %d packages for upgrade", upgradeCount);
00403 }
00404 */
00405 
00406 static int unmarkPackagesAlreadyInstalled(rpmdb db, struct pkgSet *psp)
00407 {
00408     Header h, installedHeader;
00409     char *name;
00410     struct packageInfo **pip;
00411     int count;
00412 
00413     count = psp->numPackages;
00414     pip = psp->packages;
00415     while (count--) {
00416         if ((*pip)->selected) {
00417             h = (*pip)->h;
00418             /* If this package is already installed, don't bother */
00419             name = NULL;
00420             headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
00421             if (!name) {
00422                 /* bum header */
00423                 /*logMessage("Failed with bad header");*/
00424                 return(-1);
00425             }
00426           { rpmdbMatchIterator mi;
00427 
00428             mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00429             rpmErrorSetCallback(errorFunction);
00430             while((installedHeader = rpmdbNextIterator(mi)) != NULL) {
00431                 if (rpmVersionCompare(installedHeader, h) >= 0) {
00432                     /* already have a newer version installed */
00433                     DEBUG (("Already have newer version\n"))
00434                     (*pip)->selected = 0;
00435                     break;
00436                 }
00437             }
00438             rpmdbFreeIterator(mi);
00439             rpmErrorSetCallback(NULL);
00440           }
00441         }
00442 
00443         pip++;
00444     }
00445 
00446     return 0;
00447 }
00448             
00449 static void emptyErrorCallback(void) {
00450 }
00451 
00452 int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot)
00453 {
00454     rpmdb db;
00455     struct hash_table *hashTable;
00456     rpmErrorCallBackType old;    
00457 
00458     /*logDebugMessage(("ugFindUpgradePackages() ..."));*/
00459 
00460 /*      rpmReadConfigFiles(NULL, NULL); */
00461 
00462     rpmSetVerbosity(RPMMESS_FATALERROR);
00463     old = rpmErrorSetCallback(emptyErrorCallback);
00464 
00465     if (rpmdbOpen(installRoot, &db, O_RDONLY, 0644)) {
00466         /*logMessage("failed opening %s/var/lib/rpm/packages.rpm",
00467                      installRoot);*/
00468         return(-1);
00469     }
00470 
00471     rpmErrorSetCallback(old);
00472     rpmSetVerbosity(RPMMESS_NORMAL);
00473     
00474     hashTable = htNewTable(1103);
00475 
00476     /* For all packages that are installed, if there is no package       */
00477     /* available by that name, add the package's files to the hash table */
00478     addLostFiles(db, psp, hashTable);
00479     /*logDebugMessage(("added lost files"));
00480     printCount(psp);*/
00481     
00482     /* Find packges that are new, and mark them in installThisPackage,  */
00483     /* updating availPkgs with the count.  Also add files to the hash   */
00484     /* table that do not exist in the new package - they may have moved */
00485     if (findUpgradePackages(db, psp, hashTable)) {
00486         rpmdbClose(db);
00487         return(-1);
00488     }
00489     /*logDebugMessage(("found basic packages to upgrade"));
00490     printCount(psp);
00491     hash_stats(hashTable);*/
00492 
00493     /* Remove any files that were added to the hash table that are in */
00494     /* some other package marked for upgrade.                         */
00495     removeMovedFilesAlreadyHandled(psp, hashTable);
00496     /*logDebugMessage(("removed extra files which have moved"));
00497     printCount(psp);*/
00498 
00499     findPackagesWithRelocatedFiles(psp, hashTable);
00500     /*logDebugMessage(("found packages with relocated files"));
00501     printCount(psp);*/
00502 
00503     findPackagesWithObsoletes(db, psp);
00504     /*logDebugMessage(("found packages that obsolete installed packages"));
00505     printCount(psp);*/
00506     
00507     unmarkPackagesAlreadyInstalled(db, psp);
00508     /*logDebugMessage(("unmarked packages already installed"));
00509     printCount(psp);*/
00510     
00511     htFreeHashTable(hashTable);
00512     
00513     /*printMemStats("Done");*/
00514 
00515     rpmdbClose(db);
00516 
00517     return 0;
00518 }

Generated at Thu Apr 19 15:29:44 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001