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 }