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

Generated on Tue Sep 17 15:56:43 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002