lib/psm.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include "psm.h"
00009 #include <rpmmacro.h>
00010 #include <rpmurl.h>
00011 
00012 #include "depends.h"
00013 
00014 #include "rpmlead.h"            /* writeLead proto */
00015 #include "signature.h"          /* signature constants */
00016 #include "ugid.h"
00017 #include "misc.h"
00018 #include "rpmdb.h"              /* XXX for db_chrootDone */
00019 #include "debug.h"
00020 
00021 /*@access Header @*/            /* compared with NULL */
00022 /*@access rpmTransactionSet @*/ /* compared with NULL */
00023 /*@access rpmdbMatchIterator @*/ /* compared with NULL */
00024 /*@access TFI_t @*/             /* compared with NULL */
00025 /*@access FSM_t @*/             /* compared with NULL */
00026 /*@access PSM_t @*/             /* compared with NULL */
00027 /*@access FD_t @*/              /* compared with NULL */
00028 /*@access rpmdb @*/             /* compared with NULL */
00029 
00030 #ifdef  DYING
00031 /*@-redecl -declundef -exportheadervar@*/
00032 extern const char * chroot_prefix;
00033 /*@=redecl =declundef =exportheadervar@*/
00034 #endif
00035 
00036 int rpmVersionCompare(Header first, Header second)
00037 {
00038     const char * one, * two;
00039     int_32 * epochOne, * epochTwo;
00040     int rc;
00041 
00042     if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
00043         epochOne = NULL;
00044     if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo,
00045                         NULL))
00046         epochTwo = NULL;
00047 
00048     if (epochOne && !epochTwo)
00049         return 1;
00050     else if (!epochOne && epochTwo)
00051         return -1;
00052     else if (epochOne && epochTwo) {
00053         if (*epochOne < *epochTwo)
00054             return -1;
00055         else if (*epochOne > *epochTwo)
00056             return 1;
00057     }
00058 
00059     rc = headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
00060     rc = headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
00061 
00062     rc = rpmvercmp(one, two);
00063     if (rc)
00064         return rc;
00065 
00066     (void) headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
00067     (void) headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
00068 
00069     return rpmvercmp(one, two);
00070 }
00071 
00072 void loadFi(Header h, TFI_t fi)
00073 {
00074     HGE_t hge;
00075     HFD_t hfd;
00076     uint_32 * uip;
00077     int len;
00078     int rc;
00079     int i;
00080     
00081     if (fi->fsm == NULL)
00082         fi->fsm = newFSM();
00083 
00084     /* XXX avoid gcc noise on pointer (4th arg) cast(s) */
00085     hge = (fi->type == TR_ADDED)
00086         ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry;
00087     fi->hge = hge;
00088     fi->hae = (HAE_t) headerAddEntry;
00089     fi->hme = (HME_t) headerModifyEntry;
00090     fi->hre = (HRE_t) headerRemoveEntry;
00091     fi->hfd = hfd = headerFreeData;
00092 
00093     if (h && fi->h == NULL)     fi->h = headerLink(h);
00094 
00095     /* Duplicate name-version-release so that headers can be free'd. */
00096     rc = hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL);
00097     fi->name = xstrdup(fi->name);
00098     rc = hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL);
00099     fi->version = xstrdup(fi->version);
00100     rc = hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL);
00101     fi->release = xstrdup(fi->release);
00102 
00103     /* -1 means not found */
00104     rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL);
00105     fi->epoch = (rc ? *uip : -1);
00106     /* 0 means unknown */
00107     rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL);
00108     fi->archiveSize = (rc ? *uip : 0);
00109 
00110     if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) {
00111         fi->dc = 0;
00112         fi->fc = 0;
00113         return;
00114     }
00115 
00116     rc = hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
00117     rc = hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
00118     rc = hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL);
00119     rc = hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL);
00120     rc = hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL);
00121     rc = hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL);
00122 
00123     fi->action = FA_UNKNOWN;
00124     fi->flags = 0;
00125 
00126     /* actions is initialized earlier for added packages */
00127     if (fi->actions == NULL)
00128         fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
00129 
00130     switch (fi->type) {
00131     case TR_ADDED:
00132         fi->mapflags =
00133                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00134         rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
00135         rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
00136         rc = hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL);
00137         rc = hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL);
00138         rc = hge(fi->h, RPMTAG_FILERDEVS, NULL, (void **) &fi->frdevs, NULL);
00139 
00140         /* 0 makes for noops */
00141         fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
00142 
00143         break;
00144     case TR_REMOVED:
00145         fi->mapflags = 
00146                 CPIO_MAP_ABSOLUTE | CPIO_MAP_ADDDOT | CPIO_ALL_HARDLINKS |
00147                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00148         rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
00149         rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
00150         fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)),
00151                                 fi->fsizes, fi->fc * sizeof(*fi->fsizes));
00152         fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)),
00153                                 fi->fflags, fi->fc * sizeof(*fi->fflags));
00154         fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)),
00155                                 fi->fmodes, fi->fc * sizeof(*fi->fmodes));
00156         /* XXX there's a tedious segfault here for some version(s) of rpm */
00157         if (fi->fstates)
00158             fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)),
00159                                 fi->fstates, fi->fc * sizeof(*fi->fstates));
00160         else
00161             fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates));
00162         fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)),
00163                                 fi->dil, fi->fc * sizeof(*fi->dil));
00164         fi->h = headerFree(fi->h);
00165         break;
00166     }
00167 
00168     fi->dnlmax = -1;
00169     for (i = 0; i < fi->dc; i++) {
00170         if ((len = strlen(fi->dnl[i])) > fi->dnlmax)
00171             fi->dnlmax = len;
00172     }
00173 
00174     fi->bnlmax = -1;
00175     for (i = 0; i < fi->fc; i++) {
00176         if ((len = strlen(fi->bnl[i])) > fi->bnlmax)
00177             fi->bnlmax = len;
00178     }
00179 
00180     fi->dperms = 0755;
00181     fi->fperms = 0644;
00182 
00183     /*@-nullstate@*/    /* FIX: fi->h is NULL for TR_REMOVED */
00184     return;
00185     /*@=nullstate@*/
00186 }
00187 
00188 void freeFi(TFI_t fi)
00189 {
00190     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00191 
00192     fi->name = _free(fi->name);
00193     fi->version = _free(fi->version);
00194     fi->release = _free(fi->release);
00195     fi->actions = _free(fi->actions);
00196     fi->replacedSizes = _free(fi->replacedSizes);
00197     fi->replaced = _free(fi->replaced);
00198 
00199     fi->bnl = hfd(fi->bnl, -1);
00200     fi->dnl = hfd(fi->dnl, -1);
00201     fi->obnl = hfd(fi->obnl, -1);
00202     fi->odnl = hfd(fi->odnl, -1);
00203     fi->flinks = hfd(fi->flinks, -1);
00204     fi->fmd5s = hfd(fi->fmd5s, -1);
00205     fi->fuser = hfd(fi->fuser, -1);
00206     fi->fgroup = hfd(fi->fgroup, -1);
00207     fi->flangs = hfd(fi->flangs, -1);
00208 
00209     fi->apath = _free(fi->apath);
00210     fi->fuids = _free(fi->fuids);
00211     fi->fgids = _free(fi->fgids);
00212     fi->fmapflags = _free(fi->fmapflags);
00213 
00214     fi->fsm = freeFSM(fi->fsm);
00215 
00216     switch (fi->type) {
00217     case TR_ADDED:
00218             break;
00219     case TR_REMOVED:
00220         fi->fsizes = hfd(fi->fsizes, -1);
00221         fi->fflags = hfd(fi->fflags, -1);
00222         fi->fmodes = hfd(fi->fmodes, -1);
00223         fi->fstates = hfd(fi->fstates, -1);
00224         fi->dil = hfd(fi->dil, -1);
00225         break;
00226     }
00227 
00228     fi->h = headerFree(fi->h);
00229 
00230     /*@-nullstate@*/
00231     return;
00232     /*@=nullstate@*/
00233 }
00234 
00235 /*@observer@*/ const char *const fiTypeString(TFI_t fi)
00236 {
00237     switch(fi->type) {
00238     case TR_ADDED:      return " install";
00239     case TR_REMOVED:    return "   erase";
00240     default:            return "???";
00241     }
00242     /*@noteached@*/
00243 }
00244 
00249 /*@observer@*/ /*@unchecked@*/
00250 static struct tagMacro {
00251 /*@observer@*/ /*@null@*/ const char *  macroname; 
00252     rpmTag      tag;            
00253 } tagMacros[] = {
00254     { "name",           RPMTAG_NAME },
00255     { "version",        RPMTAG_VERSION },
00256     { "release",        RPMTAG_RELEASE },
00257     { "epoch",          RPMTAG_EPOCH },
00258     { NULL, 0 }
00259 };
00260 
00267 static int rpmInstallLoadMacros(TFI_t fi, Header h)
00268         /*@globals rpmGlobalMacroContext, internalState @*/
00269         /*@modifies rpmGlobalMacroContext, internalState @*/
00270 {
00271     HGE_t hge = (HGE_t) fi->hge;
00272     struct tagMacro * tagm;
00273     union {
00274 /*@unused@*/ void * ptr;
00275 /*@unused@*/ const char ** argv;
00276         const char * str;
00277         int_32 * i32p;
00278     } body;
00279     char numbuf[32];
00280     rpmTagType type;
00281 
00282     for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
00283         if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
00284             continue;
00285         switch (type) {
00286         case RPM_INT32_TYPE:
00287             sprintf(numbuf, "%d", *body.i32p);
00288             addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
00289             /*@switchbreak@*/ break;
00290         case RPM_STRING_TYPE:
00291             addMacro(NULL, tagm->macroname, NULL, body.str, -1);
00292             /*@switchbreak@*/ break;
00293         case RPM_NULL_TYPE:
00294         case RPM_CHAR_TYPE:
00295         case RPM_INT8_TYPE:
00296         case RPM_INT16_TYPE:
00297         case RPM_BIN_TYPE:
00298         case RPM_STRING_ARRAY_TYPE:
00299         case RPM_I18NSTRING_TYPE:
00300         default:
00301             /*@switchbreak@*/ break;
00302         }
00303     }
00304     return 0;
00305 }
00306 
00314 static int mergeFiles(TFI_t fi, Header h, Header newH)
00315         /*@modifies h @*/
00316 {
00317     HGE_t hge = (HGE_t)fi->hge;
00318     HME_t hme = (HME_t)fi->hme;
00319     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00320     fileAction * actions = fi->actions;
00321     int i, j, k, fc, xx;
00322     rpmTagType type = 0;
00323     int_32 count = 0;
00324     int_32 dirNamesCount, dirCount;
00325     void * data, * newdata;
00326     int_32 * dirIndexes, * newDirIndexes;
00327     uint_32 * fileSizes, fileSize;
00328     const char ** dirNames;
00329     const char ** newDirNames;
00330     static rpmTag mergeTags[] = {
00331         RPMTAG_FILESIZES,
00332         RPMTAG_FILESTATES,
00333         RPMTAG_FILEMODES,
00334         RPMTAG_FILERDEVS,
00335         RPMTAG_FILEMTIMES,
00336         RPMTAG_FILEMD5S,
00337         RPMTAG_FILELINKTOS,
00338         RPMTAG_FILEFLAGS,
00339         RPMTAG_FILEUSERNAME,
00340         RPMTAG_FILEGROUPNAME,
00341         RPMTAG_FILEVERIFYFLAGS,
00342         RPMTAG_FILEDEVICES,
00343         RPMTAG_FILEINODES,
00344         RPMTAG_FILELANGS,
00345         RPMTAG_BASENAMES,
00346         0,
00347     };
00348     static rpmTag requireTags[] = {
00349         RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
00350         RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
00351         RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS
00352     };
00353 
00354     xx = hge(h, RPMTAG_SIZE, NULL, (void **) &fileSizes, NULL);
00355     fileSize = *fileSizes;
00356     xx = hge(newH, RPMTAG_FILESIZES, NULL, (void **) &fileSizes, &count);
00357     for (i = 0, fc = 0; i < count; i++)
00358         if (actions[i] != FA_SKIPMULTILIB) {
00359             fc++;
00360             fileSize += fileSizes[i];
00361         }
00362     xx = hme(h, RPMTAG_SIZE, RPM_INT32_TYPE, &fileSize, 1);
00363 
00364     /*@-sizeoftype@*/
00365     for (i = 0; mergeTags[i]; i++) {
00366         if (!hge(newH, mergeTags[i], &type, (void **) &data, &count))
00367             continue;
00368         switch (type) {
00369         case RPM_CHAR_TYPE:
00370         case RPM_INT8_TYPE:
00371             newdata = xcalloc(fc, sizeof(int_8));
00372             for (j = 0, k = 0; j < count; j++)
00373                 if (actions[j] != FA_SKIPMULTILIB)
00374                         ((int_8 *) newdata)[k++] = ((int_8 *) data)[j];
00375             xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00376             free (newdata);
00377             /*@switchbreak@*/ break;
00378         case RPM_INT16_TYPE:
00379             newdata = xcalloc(fc, sizeof(int_16));
00380             for (j = 0, k = 0; j < count; j++)
00381                 if (actions[j] != FA_SKIPMULTILIB)
00382                     ((int_16 *) newdata)[k++] = ((int_16 *) data)[j];
00383             xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00384             free (newdata);
00385             /*@switchbreak@*/ break;
00386         case RPM_INT32_TYPE:
00387             newdata = xcalloc(fc, sizeof(int_32));
00388             for (j = 0, k = 0; j < count; j++)
00389                 if (actions[j] != FA_SKIPMULTILIB)
00390                     ((int_32 *) newdata)[k++] = ((int_32 *) data)[j];
00391             xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00392             free (newdata);
00393             /*@switchbreak@*/ break;
00394         case RPM_STRING_ARRAY_TYPE:
00395             newdata = xcalloc(fc, sizeof(char *));
00396             for (j = 0, k = 0; j < count; j++)
00397                 if (actions[j] != FA_SKIPMULTILIB)
00398                     ((char **) newdata)[k++] = ((char **) data)[j];
00399             xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00400             free (newdata);
00401             /*@switchbreak@*/ break;
00402         default:
00403             rpmError(RPMERR_DATATYPE, _("Data type %d not supported\n"),
00404                         (int) type);
00405             return 1;
00406             /*@notreached@*/ /*@switchbreak@*/ break;
00407         }
00408         data = hfd(data, type);
00409     }
00410     /*@=sizeoftype@*/
00411     xx = hge(newH, RPMTAG_DIRINDEXES, NULL, (void **) &newDirIndexes, &count);
00412     xx = hge(newH, RPMTAG_DIRNAMES, NULL, (void **) &newDirNames, NULL);
00413     xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00414     xx = hge(h, RPMTAG_DIRNAMES, NULL, (void **) &data, &dirNamesCount);
00415 
00416     dirNames = xcalloc(dirNamesCount + fc, sizeof(*dirNames));
00417     for (i = 0; i < dirNamesCount; i++)
00418         dirNames[i] = ((char **) data)[i];
00419     dirCount = dirNamesCount;
00420     newdata = xcalloc(fc, sizeof(*newDirIndexes));
00421     for (i = 0, k = 0; i < count; i++) {
00422         if (actions[i] == FA_SKIPMULTILIB)
00423             continue;
00424         for (j = 0; j < dirCount; j++)
00425             if (!strcmp(dirNames[j], newDirNames[newDirIndexes[i]]))
00426                 /*@innerbreak@*/ break;
00427         if (j == dirCount)
00428             dirNames[dirCount++] = newDirNames[newDirIndexes[i]];
00429         ((int_32 *) newdata)[k++] = j;
00430     }
00431     xx = headerAddOrAppendEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, newdata, fc);
00432     if (dirCount > dirNamesCount)
00433         xx = headerAddOrAppendEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00434                                dirNames + dirNamesCount,
00435                                dirCount - dirNamesCount);
00436     data = hfd(data, -1);
00437     newDirNames = hfd(newDirNames, -1);
00438     free (newdata);
00439     free (dirNames);
00440 
00441     for (i = 0; i < 9; i += 3) {
00442         const char **Names, **EVR, **newNames, **newEVR;
00443         rpmTagType nnt, nvt, rnt;
00444         uint_32 *Flags, *newFlags;
00445         int Count = 0, newCount = 0;
00446 
00447         if (!hge(newH, requireTags[i], &nnt, (void **) &newNames, &newCount))
00448             continue;
00449 
00450         xx = hge(newH, requireTags[i+1], &nvt, (void **) &newEVR, NULL);
00451         xx = hge(newH, requireTags[i+2], NULL, (void **) &newFlags, NULL);
00452         if (hge(h, requireTags[i], &rnt, (void **) &Names, &Count))
00453         {
00454             (void) hge(h, requireTags[i+1], NULL, (void **) &EVR, NULL);
00455             (void) hge(h, requireTags[i+2], NULL, (void **) &Flags, NULL);
00456             for (j = 0; j < newCount; j++)
00457                 for (k = 0; k < Count; k++)
00458                     if (!strcmp (newNames[j], Names[k])
00459                         && !strcmp (newEVR[j], EVR[k])
00460                         && (newFlags[j] & RPMSENSE_SENSEMASK) ==
00461                            (Flags[k] & RPMSENSE_SENSEMASK))
00462                     {
00463                         newNames[j] = NULL;
00464                         /*@innerbreak@*/ break;
00465                     }
00466         }
00467         for (j = 0, k = 0; j < newCount; j++) {
00468             if (!newNames[j] || !isDependsMULTILIB(newFlags[j]))
00469                 /*@innercontinue@*/ continue;
00470             if (j != k) {
00471                 newNames[k] = newNames[j];
00472                 newEVR[k] = newEVR[j];
00473                 newFlags[k] = newFlags[j];
00474             }
00475             k++;
00476         }
00477         if (k) {
00478             xx = headerAddOrAppendEntry(h, requireTags[i],
00479                                        RPM_STRING_ARRAY_TYPE, newNames, k);
00480             xx = headerAddOrAppendEntry(h, requireTags[i+1],
00481                                        RPM_STRING_ARRAY_TYPE, newEVR, k);
00482             xx = headerAddOrAppendEntry(h, requireTags[i+2], RPM_INT32_TYPE,
00483                                        newFlags, k);
00484         }
00485         newNames = hfd(newNames, nnt);
00486         newEVR = hfd(newEVR, nvt);
00487         Names = hfd(Names, rnt);
00488     }
00489     return 0;
00490 }
00491 
00497 static int markReplacedFiles(PSM_t psm)
00498         /*@globals fileSystem @*/
00499         /*@modifies psm, fileSystem @*/
00500 {
00501     const rpmTransactionSet ts = psm->ts;
00502     TFI_t fi = psm->fi;
00503     HGE_t hge = (HGE_t)fi->hge;
00504     const struct sharedFileInfo * replaced = fi->replaced;
00505     const struct sharedFileInfo * sfi;
00506     rpmdbMatchIterator mi;
00507     Header h;
00508     unsigned int * offsets;
00509     unsigned int prev;
00510     int num, xx;
00511 
00512     if (!(fi->fc > 0 && fi->replaced))
00513         return 0;
00514 
00515     num = prev = 0;
00516     for (sfi = replaced; sfi->otherPkg; sfi++) {
00517         if (prev && prev == sfi->otherPkg)
00518             continue;
00519         prev = sfi->otherPkg;
00520         num++;
00521     }
00522     if (num == 0)
00523         return 0;
00524 
00525     offsets = alloca(num * sizeof(*offsets));
00526     num = prev = 0;
00527     for (sfi = replaced; sfi->otherPkg; sfi++) {
00528         if (prev && prev == sfi->otherPkg)
00529             continue;
00530         prev = sfi->otherPkg;
00531         offsets[num++] = sfi->otherPkg;
00532     }
00533 
00534     mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
00535     xx = rpmdbAppendIterator(mi, offsets, num);
00536     xx = rpmdbSetIteratorRewrite(mi, 1);
00537 
00538     sfi = replaced;
00539     while ((h = rpmdbNextIterator(mi)) != NULL) {
00540         char * secStates;
00541         int modified;
00542         int count;
00543 
00544         modified = 0;
00545 
00546         if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
00547             continue;
00548         
00549         prev = rpmdbGetIteratorOffset(mi);
00550         num = 0;
00551         while (sfi->otherPkg && sfi->otherPkg == prev) {
00552             assert(sfi->otherFileNum < count);
00553             if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
00554                 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
00555                 if (modified == 0) {
00556                     /* Modified header will be rewritten. */
00557                     modified = 1;
00558                     xx = rpmdbSetIteratorModified(mi, modified);
00559                 }
00560                 num++;
00561             }
00562             sfi++;
00563         }
00564     }
00565     mi = rpmdbFreeIterator(mi);
00566 
00567     return 0;
00568 }
00569 
00577 static rpmRC chkdir (const char * dpath, const char * dname)
00578         /*@globals fileSystem @*/
00579         /*@modifies fileSystem @*/
00580 {
00581     struct stat st;
00582     int rc;
00583 
00584     if ((rc = Stat(dpath, &st)) < 0) {
00585         int ut = urlPath(dpath, NULL);
00586         switch (ut) {
00587         case URL_IS_PATH:
00588         case URL_IS_UNKNOWN:
00589             if (errno != ENOENT)
00590                 break;
00591             /*@fallthrough@*/
00592         case URL_IS_FTP:
00593         case URL_IS_HTTP:
00594             rc = Mkdir(dpath, 0755);
00595             break;
00596         case URL_IS_DASH:
00597             break;
00598         }
00599         if (rc < 0) {
00600             rpmError(RPMERR_CREATE, _("cannot create %%%s %s\n"),
00601                         dname, dpath);
00602             return RPMRC_FAIL;
00603         }
00604     }
00605     if ((rc = Access(dpath, W_OK))) {
00606         rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"), dname, dpath);
00607         return RPMRC_FAIL;
00608     }
00609     return RPMRC_OK;
00610 }
00611 
00612 rpmRC rpmInstallSourcePackage(const char * rootDir, FD_t fd,
00613                         const char ** specFilePtr,
00614                         rpmCallbackFunction notify, rpmCallbackData notifyData,
00615                         char ** cookie)
00616 {
00617     rpmdb rpmdb = NULL;
00618     rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
00619     TFI_t fi = xcalloc(sizeof(*fi), 1);
00620     const char * _sourcedir = NULL;
00621     const char * _specdir = NULL;
00622     const char * specFile = NULL;
00623     HGE_t hge;
00624     HFD_t hfd;
00625     Header h = NULL;
00626     struct psm_s psmbuf;
00627     PSM_t psm = &psmbuf;
00628     int isSource;
00629     rpmRC rc;
00630     int i;
00631 
00632     ts->notify = notify;
00633     /*@-temptrans -assignexpose@*/
00634     ts->notifyData = notifyData;
00635     /*@=temptrans =assignexpose@*/
00636 
00637     /*@-mustmod@*/      /* LCL: segfault */
00638     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00639     /*@=mustmod@*/
00640     if (rc)
00641         goto exit;
00642 
00643     if (!isSource) {
00644         rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
00645         rc = RPMRC_FAIL;
00646         goto exit;
00647     }
00648 
00649     (void) rpmtransAddPackage(ts, h, fd, NULL, 0, NULL);
00650     if (ts->addedPackages.list == NULL) {       /* XXX can't happen */
00651         rc = RPMRC_FAIL;
00652         goto exit;
00653     }
00654 
00655     fi->type = TR_ADDED;
00656     fi->ap = ts->addedPackages.list;
00657     loadFi(h, fi);
00658     hge = fi->hge;
00659     hfd = (fi->hfd ? fi->hfd : headerFreeData);
00660     h = headerFree(h);  /* XXX reference held by transaction set */
00661 
00662     (void) rpmInstallLoadMacros(fi, fi->h);
00663 
00664     memset(psm, 0, sizeof(*psm));
00665     psm->ts = ts;
00666     psm->fi = fi;
00667 
00668     if (cookie) {
00669         *cookie = NULL;
00670         if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
00671             *cookie = xstrdup(*cookie);
00672     }
00673 
00674     /* XXX FIXME: can't do endian neutral MD5 verification yet. */
00675     fi->fmd5s = hfd(fi->fmd5s, -1);
00676 
00677     /* XXX FIXME: don't do per-file mapping, force global flags. */
00678     fi->fmapflags = _free(fi->fmapflags);
00679     fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00680 
00681     fi->uid = getuid();
00682     fi->gid = getgid();
00683     fi->astriplen = 0;
00684     fi->striplen = 0;
00685 
00686     fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
00687     fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
00688     for (i = 0; i < fi->fc; i++) {
00689         fi->fuids[i] = fi->uid;
00690         fi->fgids[i] = fi->gid;
00691     }
00692 
00693     for (i = 0; i < fi->fc; i++)
00694         fi->actions[i] = FA_CREATE;
00695 
00696     rpmBuildFileList(fi->h, &fi->apath, NULL);
00697 
00698     i = fi->fc;
00699     if (headerIsEntry(fi->h, RPMTAG_COOKIE))
00700         for (i = 0; i < fi->fc; i++)
00701                 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
00702 
00703     if (i == fi->fc) {
00704         /* Find the spec file by name. */
00705         for (i = 0; i < fi->fc; i++) {
00706             const char * t = fi->apath[i];
00707             t += strlen(fi->apath[i]) - 5;
00708             if (!strcmp(t, ".spec")) break;
00709         }
00710     }
00711 
00712     _sourcedir = rpmGenPath(ts->rootDir, "%{_sourcedir}", "");
00713     rc = chkdir(_sourcedir, "sourcedir");
00714     if (rc) {
00715         rc = RPMRC_FAIL;
00716         goto exit;
00717     }
00718 
00719     _specdir = rpmGenPath(ts->rootDir, "%{_specdir}", "");
00720     rc = chkdir(_specdir, "specdir");
00721     if (rc) {
00722         rc = RPMRC_FAIL;
00723         goto exit;
00724     }
00725 
00726     /* Build dnl/dil with {_sourcedir, _specdir} as values. */
00727     if (i < fi->fc) {
00728         int speclen = strlen(_specdir) + 2;
00729         int sourcelen = strlen(_sourcedir) + 2;
00730         char * t;
00731 
00732         fi->dnl = hfd(fi->dnl, -1);
00733 
00734         fi->dc = 2;
00735         fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl) + fi->fc * sizeof(*fi->dil) +
00736                         speclen + sourcelen);
00737         fi->dil = (int *)(fi->dnl + fi->dc);
00738         memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
00739         fi->dil[i] = 1;
00740         /*@-dependenttrans@*/
00741         fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
00742         fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
00743         /*@=dependenttrans@*/
00744         (void) stpcpy( stpcpy(t, _specdir), "/");
00745 
00746         t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
00747         (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
00748         specFile = t;
00749     } else {
00750         rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
00751         rc = RPMRC_FAIL;
00752         goto exit;
00753     }
00754 
00755     psm->goal = PSM_PKGINSTALL;
00756 
00757     /*@-compmempass@*/  /* FIX: psm->fi->dnl should be owned. */
00758     rc = psmStage(psm, PSM_PROCESS);
00759 
00760     (void) psmStage(psm, PSM_FINI);
00761     /*@=compmempass@*/
00762 
00763     if (rc) rc = RPMRC_FAIL;
00764 
00765 exit:
00766     if (specFilePtr && specFile && rc == RPMRC_OK)
00767         *specFilePtr = specFile;
00768     else
00769         specFile = _free(specFile);
00770 
00771     _specdir = _free(_specdir);
00772     _sourcedir = _free(_sourcedir);
00773 
00774     if (h) h = headerFree(h);
00775 
00776     if (fi) {
00777         freeFi(fi);
00778         fi = _free(fi);
00779     }
00780     ts = rpmtransFree(ts);
00781 
00782     return rc;
00783 }
00784 
00785 /*@observer@*/ /*@unchecked@*/
00786 static char * SCRIPT_PATH =
00787         "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
00788 
00794 static /*@observer@*/ const char * const tag2sln(int tag)
00795         /*@*/
00796 {
00797     switch (tag) {
00798     case RPMTAG_PREIN:          return "%pre";
00799     case RPMTAG_POSTIN:         return "%post";
00800     case RPMTAG_PREUN:          return "%preun";
00801     case RPMTAG_POSTUN:         return "%postun";
00802     case RPMTAG_VERIFYSCRIPT:   return "%verify";
00803     }
00804     return "%unknownscript";
00805 }
00806 
00825 static int runScript(PSM_t psm, Header h,
00826                 const char * sln,
00827                 int progArgc, const char ** progArgv, 
00828                 const char * script, int arg1, int arg2)
00829         /*@globals rpmGlobalMacroContext,
00830                 fileSystem, internalState@*/
00831         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
00832 {
00833     const rpmTransactionSet ts = psm->ts;
00834     TFI_t fi = psm->fi;
00835     HGE_t hge = fi->hge;
00836     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00837     const char ** argv = NULL;
00838     int argc = 0;
00839     const char ** prefixes = NULL;
00840     int numPrefixes;
00841     rpmTagType ipt;
00842     const char * oldPrefix;
00843     int maxPrefixLength;
00844     int len;
00845     char * prefixBuf = NULL;
00846     pid_t child;
00847     int status = 0;
00848     const char * fn = NULL;
00849     int i, xx;
00850     int freePrefixes = 0;
00851     FD_t out;
00852     rpmRC rc = RPMRC_OK;
00853     const char *n, *v, *r;
00854 
00855     if (!progArgv && !script)
00856         return 0;
00857 
00858     if (!progArgv) {
00859         argv = alloca(5 * sizeof(*argv));
00860         argv[0] = "/bin/sh";
00861         argc = 1;
00862     } else {
00863         argv = alloca((progArgc + 4) * sizeof(*argv));
00864         memcpy(argv, progArgv, progArgc * sizeof(*argv));
00865         argc = progArgc;
00866     }
00867 
00868     xx = headerNVR(h, &n, &v, &r);
00869     if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
00870         freePrefixes = 1;
00871     } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
00872         prefixes = &oldPrefix;
00873         numPrefixes = 1;
00874     } else {
00875         numPrefixes = 0;
00876     }
00877 
00878     maxPrefixLength = 0;
00879     for (i = 0; i < numPrefixes; i++) {
00880         len = strlen(prefixes[i]);
00881         if (len > maxPrefixLength) maxPrefixLength = len;
00882     }
00883     prefixBuf = alloca(maxPrefixLength + 50);
00884 
00885     if (script) {
00886         FD_t fd;
00887         /*@-branchstate@*/
00888         if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) {
00889             if (freePrefixes) free(prefixes);
00890             return 1;
00891         }
00892         /*@=branchstate@*/
00893 
00894         if (rpmIsDebug() &&
00895             (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
00896             xx = Fwrite("set -x\n", sizeof(char), 7, fd);
00897 
00898         xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
00899         xx = Fclose(fd);
00900 
00901         {   const char * sn = fn;
00902             if (!ts->chrootDone &&
00903                 !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0'))
00904             {
00905                 sn += strlen(ts->rootDir)-1;
00906             }
00907             argv[argc++] = sn;
00908         }
00909 
00910         if (arg1 >= 0) {
00911             char *av = alloca(20);
00912             sprintf(av, "%d", arg1);
00913             argv[argc++] = av;
00914         }
00915         if (arg2 >= 0) {
00916             char *av = alloca(20);
00917             sprintf(av, "%d", arg2);
00918             argv[argc++] = av;
00919         }
00920     }
00921 
00922     argv[argc] = NULL;
00923 
00924     if (ts->scriptFd != NULL) {
00925         if (rpmIsVerbose()) {
00926             out = fdDup(Fileno(ts->scriptFd));
00927         } else {
00928             out = Fopen("/dev/null", "w.fdio");
00929             if (Ferror(out)) {
00930                 out = fdDup(Fileno(ts->scriptFd));
00931             }
00932         }
00933     } else {
00934         out = fdDup(STDOUT_FILENO);
00935 #ifdef  DYING
00936         out = fdLink(out, "runScript persist");
00937 #endif
00938     }
00939     if (out == NULL) return 1;  /* XXX can't happen */
00940     
00941     /*@-branchstate@*/
00942     if (!(child = fork())) {
00943         const char * rootDir;
00944         int pipes[2];
00945 
00946         pipes[0] = pipes[1] = 0;
00947         /* make stdin inaccessible */
00948         xx = pipe(pipes);
00949         xx = close(pipes[1]);
00950         xx = dup2(pipes[0], STDIN_FILENO);
00951         xx = close(pipes[0]);
00952 
00953         if (ts->scriptFd != NULL) {
00954             if (Fileno(ts->scriptFd) != STDERR_FILENO)
00955                 xx = dup2(Fileno(ts->scriptFd), STDERR_FILENO);
00956             if (Fileno(out) != STDOUT_FILENO)
00957                 xx = dup2(Fileno(out), STDOUT_FILENO);
00958             /* make sure we don't close stdin/stderr/stdout by mistake! */
00959             if (Fileno(out) > STDERR_FILENO && Fileno(out) != Fileno(ts->scriptFd)) {
00960                 xx = Fclose (out);
00961             }
00962             if (Fileno(ts->scriptFd) > STDERR_FILENO) {
00963                 xx = Fclose (ts->scriptFd);
00964             }
00965         }
00966 
00967         {   const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
00968             const char *path = SCRIPT_PATH;
00969 
00970             if (ipath && ipath[5] != '%')
00971                 path = ipath;
00972             xx = doputenv(path);
00973             /*@-modobserver@*/
00974             ipath = _free(ipath);
00975             /*@=modobserver@*/
00976         }
00977 
00978         for (i = 0; i < numPrefixes; i++) {
00979             sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
00980             xx = doputenv(prefixBuf);
00981 
00982             /* backwards compatibility */
00983             if (i == 0) {
00984                 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
00985                 xx = doputenv(prefixBuf);
00986             }
00987         }
00988 
00989         if ((rootDir = ts->rootDir) != NULL)    /* XXX can't happen */
00990         switch(urlIsURL(rootDir)) {
00991         case URL_IS_PATH:
00992             rootDir += sizeof("file://") - 1;
00993             rootDir = strchr(rootDir, '/');
00994             /*@fallthrough@*/
00995         case URL_IS_UNKNOWN:
00996             if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) {
00997                 /*@-unrecog -superuser @*/
00998                 xx = chroot(rootDir);
00999                 /*@=unrecog =superuser @*/
01000             }
01001             xx = chdir("/");
01002             xx = execv(argv[0], (char *const *)argv);
01003             break;
01004         default:
01005             break;
01006         }
01007 
01008         _exit(-1);
01009         /*@notreached@*/
01010     }
01011     /*@=branchstate@*/
01012 
01013     if (waitpid(child, &status, 0) < 0) {
01014         rpmError(RPMERR_SCRIPT,
01015      _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"),
01016                  sln, n, v, r, strerror (errno));
01017         /* XXX what to do here? */
01018         rc = RPMRC_OK;
01019     } else {
01020         if (!WIFEXITED(status) || WEXITSTATUS(status)) {
01021             rpmError(RPMERR_SCRIPT,
01022      _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"),
01023                      sln, n, v, r, WEXITSTATUS(status));
01024             rc = RPMRC_FAIL;
01025         }
01026     }
01027 
01028     if (freePrefixes) prefixes = hfd(prefixes, ipt);
01029 
01030     xx = Fclose(out);   /* XXX dup'd STDOUT_FILENO */
01031     
01032     if (script) {
01033         if (!rpmIsDebug())
01034             xx = unlink(fn);
01035         fn = _free(fn);
01036     }
01037 
01038     return rc;
01039 }
01040 
01046 static rpmRC runInstScript(PSM_t psm)
01047         /*@globals rpmGlobalMacroContext,
01048                 fileSystem, internalState @*/
01049         /*@modifies psm, rpmGlobalMacroContext,
01050                 fileSystem, internalState @*/
01051 {
01052     TFI_t fi = psm->fi;
01053     HGE_t hge = fi->hge;
01054     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01055     void ** programArgv;
01056     int programArgc;
01057     const char ** argv;
01058     rpmTagType ptt, stt;
01059     const char * script;
01060     rpmRC rc = RPMRC_OK;
01061     int xx;
01062 
01063     /*
01064      * headerGetEntry() sets the data pointer to NULL if the entry does
01065      * not exist.
01066      */
01067     xx = hge(fi->h, psm->progTag, &ptt, (void **) &programArgv, &programArgc);
01068     xx = hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
01069 
01070     if (programArgv && ptt == RPM_STRING_TYPE) {
01071         argv = alloca(sizeof(char *));
01072         *argv = (const char *) programArgv;
01073     } else {
01074         argv = (const char **) programArgv;
01075     }
01076 
01077     rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), programArgc, argv,
01078                 script, psm->scriptArg, -1);
01079 
01080     programArgv = hfd(programArgv, ptt);
01081     script = hfd(script, stt);
01082     return rc;
01083 }
01084 
01093 static int handleOneTrigger(PSM_t psm, Header sourceH, Header triggeredH,
01094                         int arg2, unsigned char * triggersAlreadyRun)
01095         /*@globals rpmGlobalMacroContext,
01096                 fileSystem, internalState@*/
01097         /*@modifies psm, triggeredH, *triggersAlreadyRun, rpmGlobalMacroContext,
01098                 fileSystem, internalState @*/
01099 {
01100     const rpmTransactionSet ts = psm->ts;
01101     TFI_t fi = psm->fi;
01102     HGE_t hge = fi->hge;
01103     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01104     const char ** triggerNames;
01105     const char ** triggerEVR;
01106     const char ** triggerScripts;
01107     const char ** triggerProgs;
01108     int_32 * triggerFlags;
01109     int_32 * triggerIndices;
01110     rpmTagType tnt, tvt, tft;
01111     const char * triggerPackageName;
01112     const char * sourceName;
01113     int numTriggers;
01114     rpmRC rc = RPMRC_OK;
01115     int i;
01116     int skip;
01117     int xx;
01118 
01119     if (!(      hge(triggeredH, RPMTAG_TRIGGERNAME, &tnt, 
01120                         (void **) &triggerNames, &numTriggers) &&
01121                 hge(triggeredH, RPMTAG_TRIGGERFLAGS, &tft,
01122                         (void **) &triggerFlags, NULL) &&
01123                 hge(triggeredH, RPMTAG_TRIGGERVERSION, &tvt,
01124                         (void **) &triggerEVR, NULL))
01125         )
01126         return 0;
01127 
01128     xx = headerNVR(sourceH, &sourceName, NULL, NULL);
01129 
01130     for (i = 0; i < numTriggers; i++) {
01131         rpmTagType tit, tst, tpt;
01132 
01133         if (!(triggerFlags[i] & psm->sense)) continue;
01134         if (strcmp(triggerNames[i], sourceName)) continue;
01135 
01136         /*
01137          * For some reason, the TRIGGERVERSION stuff includes the name of
01138          * the package which the trigger is based on. We need to skip
01139          * over that here. I suspect that we'll change our minds on this
01140          * and remove that, so I'm going to just 'do the right thing'.
01141          */
01142         skip = strlen(triggerNames[i]);
01143         if (!strncmp(triggerEVR[i], triggerNames[i], skip) &&
01144             (triggerEVR[i][skip] == '-'))
01145             skip++;
01146         else
01147             skip = 0;
01148 
01149         if (!headerMatchesDepFlags(sourceH, triggerNames[i],
01150                 triggerEVR[i] + skip, triggerFlags[i]))
01151             continue;
01152 
01153         if (!(  hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
01154                        (void **) &triggerIndices, NULL) &&
01155                 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
01156                        (void **) &triggerScripts, NULL) &&
01157                 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
01158                        (void **) &triggerProgs, NULL))
01159             )
01160             continue;
01161 
01162         xx = headerNVR(triggeredH, &triggerPackageName, NULL, NULL);
01163 
01164         {   int arg1;
01165             int index;
01166 
01167             arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName);
01168             if (arg1 < 0) {
01169                 /* XXX W2DO? same as "execution of script failed" */
01170                 rc = RPMRC_FAIL;
01171             } else {
01172                 arg1 += psm->countCorrection;
01173                 index = triggerIndices[i];
01174                 if (triggersAlreadyRun == NULL ||
01175                     triggersAlreadyRun[index] == 0)
01176                 {
01177                     rc = runScript(psm, triggeredH, "%trigger", 1,
01178                             triggerProgs + index, triggerScripts[index], 
01179                             arg1, arg2);
01180                     if (triggersAlreadyRun != NULL)
01181                         triggersAlreadyRun[index] = 1;
01182                 }
01183             }
01184         }
01185 
01186         triggerIndices = hfd(triggerIndices, tit);
01187         triggerScripts = hfd(triggerScripts, tst);
01188         triggerProgs = hfd(triggerProgs, tpt);
01189 
01190         /*
01191          * Each target/source header pair can only result in a single
01192          * script being run.
01193          */
01194         break;
01195     }
01196 
01197     triggerNames = hfd(triggerNames, tnt);
01198     triggerFlags = hfd(triggerFlags, tft);
01199     triggerEVR = hfd(triggerEVR, tvt);
01200 
01201     return rc;
01202 }
01203 
01209 static int runTriggers(PSM_t psm)
01210         /*@globals rpmGlobalMacroContext,
01211                 fileSystem, internalState @*/
01212         /*@modifies psm, rpmGlobalMacroContext,
01213                 fileSystem, internalState @*/
01214 {
01215     const rpmTransactionSet ts = psm->ts;
01216     TFI_t fi = psm->fi;
01217     int numPackage;
01218     rpmRC rc = RPMRC_OK;
01219 
01220     numPackage = rpmdbCountPackages(ts->rpmdb, fi->name) + psm->countCorrection;
01221     if (numPackage < 0)
01222         return 1;
01223 
01224     {   Header triggeredH;
01225         rpmdbMatchIterator mi;
01226         int countCorrection = psm->countCorrection;
01227 
01228         psm->countCorrection = 0;
01229         mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, fi->name, 0);
01230         while((triggeredH = rpmdbNextIterator(mi)) != NULL) {
01231             rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
01232         }
01233 
01234         mi = rpmdbFreeIterator(mi);
01235         psm->countCorrection = countCorrection;
01236     }
01237 
01238     return rc;
01239 }
01240 
01246 static int runImmedTriggers(PSM_t psm)
01247         /*@globals rpmGlobalMacroContext,
01248                 fileSystem, internalState @*/
01249         /*@modifies psm, rpmGlobalMacroContext,
01250                 fileSystem, internalState @*/
01251 {
01252     const rpmTransactionSet ts = psm->ts;
01253     TFI_t fi = psm->fi;
01254     HGE_t hge = fi->hge;
01255     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01256     const char ** triggerNames;
01257     int numTriggers;
01258     int_32 * triggerIndices;
01259     rpmTagType tnt, tit;
01260     int numTriggerIndices;
01261     unsigned char * triggersRun;
01262     rpmRC rc = RPMRC_OK;
01263 
01264     if (!(      hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
01265                         (void **) &triggerNames, &numTriggers) &&
01266                 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
01267                         (void **) &triggerIndices, &numTriggerIndices))
01268         )
01269         return 0;
01270 
01271     triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
01272     memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
01273 
01274     {   Header sourceH = NULL;
01275         int i;
01276 
01277         for (i = 0; i < numTriggers; i++) {
01278             rpmdbMatchIterator mi;
01279 
01280             if (triggersRun[triggerIndices[i]] != 0) continue;
01281         
01282             mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, triggerNames[i], 0);
01283 
01284             while((sourceH = rpmdbNextIterator(mi)) != NULL) {
01285                 rc |= handleOneTrigger(psm, sourceH, fi->h, 
01286                                 rpmdbGetIteratorCount(mi),
01287                                 triggersRun);
01288             }
01289 
01290             mi = rpmdbFreeIterator(mi);
01291         }
01292     }
01293     triggerIndices = hfd(triggerIndices, tit);
01294     triggerNames = hfd(triggerNames, tnt);
01295     return rc;
01296 }
01297 
01298 /*@observer@*/ static const char *const pkgStageString(pkgStage a)
01299         /*@*/
01300 {
01301     switch(a) {
01302     case PSM_UNKNOWN:           return "unknown";
01303 
01304     case PSM_PKGINSTALL:        return "  install";
01305     case PSM_PKGERASE:          return "    erase";
01306     case PSM_PKGCOMMIT:         return "   commit";
01307     case PSM_PKGSAVE:           return "repackage";
01308 
01309     case PSM_INIT:              return "init";
01310     case PSM_PRE:               return "pre";
01311     case PSM_PROCESS:           return "process";
01312     case PSM_POST:              return "post";
01313     case PSM_UNDO:              return "undo";
01314     case PSM_FINI:              return "fini";
01315 
01316     case PSM_CREATE:            return "create";
01317     case PSM_NOTIFY:            return "notify";
01318     case PSM_DESTROY:           return "destroy";
01319     case PSM_COMMIT:            return "commit";
01320 
01321     case PSM_CHROOT_IN:         return "chrootin";
01322     case PSM_CHROOT_OUT:        return "chrootout";
01323     case PSM_SCRIPT:            return "script";
01324     case PSM_TRIGGERS:          return "triggers";
01325     case PSM_IMMED_TRIGGERS:    return "immedtriggers";
01326 
01327     case PSM_RPMIO_FLAGS:       return "rpmioflags";
01328 
01329     case PSM_RPMDB_LOAD:        return "rpmdbload";
01330     case PSM_RPMDB_ADD:         return "rpmdbadd";
01331     case PSM_RPMDB_REMOVE:      return "rpmdbremove";
01332 
01333     default:                    return "???";
01334     }
01335     /*@noteached@*/
01336 }
01337 
01342 int psmStage(PSM_t psm, pkgStage stage)
01343 {
01344     const rpmTransactionSet ts = psm->ts;
01345     TFI_t fi = psm->fi;
01346     HGE_t hge = fi->hge;
01347     HME_t hme = fi->hme;
01348     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01349     rpmRC rc = psm->rc;
01350     int saveerrno;
01351     int xx;
01352 
01353     /*@-branchstate@*/
01354     switch (stage) {
01355     case PSM_UNKNOWN:
01356         break;
01357     case PSM_INIT:
01358         rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"),
01359                 psm->stepName, fi->name, fi->version, fi->release,
01360                 fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST));
01361 
01362         /*
01363          * When we run scripts, we pass an argument which is the number of 
01364          * versions of this package that will be installed when we are
01365          * finished.
01366          */
01367         psm->npkgs_installed = rpmdbCountPackages(ts->rpmdb, fi->name);
01368         if (psm->npkgs_installed < 0) {
01369             rc = RPMRC_FAIL;
01370             break;
01371         }
01372 
01373         if (psm->goal == PSM_PKGINSTALL) {
01374             psm->scriptArg = psm->npkgs_installed + 1;
01375 
01376 assert(psm->mi == NULL);
01377             psm->mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, fi->name, 0);
01378             xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION,
01379                         RPMMIRE_DEFAULT, fi->version);
01380             xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE,
01381                         RPMMIRE_DEFAULT, fi->release);
01382 
01383             while ((psm->oh = rpmdbNextIterator(psm->mi))) {
01384                 fi->record = rpmdbGetIteratorOffset(psm->mi);
01385                 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB)
01386                     psm->oh = headerCopy(psm->oh);
01387                 else
01388                     psm->oh = NULL;
01389                 /*@loopbreak@*/ break;
01390             }
01391             psm->mi = rpmdbFreeIterator(psm->mi);
01392             rc = RPMRC_OK;
01393 
01394             if (fi->fc > 0 && fi->fstates == NULL) {
01395                 fi->fstates = xmalloc(sizeof(*fi->fstates) * fi->fc);
01396                 memset(fi->fstates, RPMFILE_STATE_NORMAL, fi->fc);
01397             }
01398 
01399             if (fi->fc <= 0)                            break;
01400             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01401         
01402             /*
01403              * Old format relocateable packages need the entire default
01404              * prefix stripped to form the cpio list, while all other packages
01405              * need the leading / stripped.
01406              */
01407             {   const char * p;
01408                 rc = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
01409                 fi->striplen = (rc ? strlen(p) + 1 : 1); 
01410             }
01411             fi->mapflags =
01412                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01413         
01414             if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
01415                 buildOrigFileList(fi->h, &fi->apath, NULL);
01416             else
01417                 rpmBuildFileList(fi->h, &fi->apath, NULL);
01418         
01419             if (fi->fuser == NULL)
01420                 xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
01421                                 (void **) &fi->fuser, NULL);
01422             if (fi->fgroup == NULL)
01423                 xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
01424                                 (void **) &fi->fgroup, NULL);
01425             if (fi->fuids == NULL)
01426                 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01427             if (fi->fgids == NULL)
01428                 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01429             rc = RPMRC_OK;
01430         }
01431         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
01432             psm->scriptArg = psm->npkgs_installed - 1;
01433         
01434             /* Retrieve installed header. */
01435             rc = psmStage(psm, PSM_RPMDB_LOAD);
01436         }
01437         if (psm->goal == PSM_PKGSAVE) {
01438             /* Open output package for writing. */
01439             {   const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
01440                 const char * pkgbn =
01441                         headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
01442 
01443                 bfmt = _free(bfmt);
01444                 psm->pkgURL = rpmGenPath("%{?_repackage_root:%{_repackage_root}}",
01445                                          "%{?_repackage_dir:%{_repackage_dir}}",
01446                                         pkgbn);
01447                 pkgbn = _free(pkgbn);
01448                 (void) urlPath(psm->pkgURL, &psm->pkgfn);
01449                 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
01450                 if (psm->fd == NULL || Ferror(psm->fd)) {
01451                     rc = RPMRC_FAIL;
01452                     break;
01453                 }
01454             }
01455         }
01456         break;
01457     case PSM_PRE:
01458         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01459 
01460         /* Change root directory if requested and not already done. */
01461         rc = psmStage(psm, PSM_CHROOT_IN);
01462 
01463         if (psm->goal == PSM_PKGINSTALL) {
01464             psm->scriptTag = RPMTAG_PREIN;
01465             psm->progTag = RPMTAG_PREINPROG;
01466 
01467             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
01468                 /* XXX FIXME: implement %triggerprein. */
01469             }
01470 
01471             if (!(ts->transFlags & RPMTRANS_FLAG_NOPRE)) {
01472                 rc = psmStage(psm, PSM_SCRIPT);
01473                 if (rc) {
01474                     rpmError(RPMERR_SCRIPT,
01475                         _("%s: %s scriptlet failed (%d), skipping %s-%s-%s\n"),
01476                         psm->stepName, tag2sln(psm->scriptTag), rc,
01477                         fi->name, fi->version, fi->release);
01478                     break;
01479                 }
01480             }
01481         }
01482 
01483         if (psm->goal == PSM_PKGERASE) {
01484             psm->scriptTag = RPMTAG_PREUN;
01485             psm->progTag = RPMTAG_PREUNPROG;
01486             psm->sense = RPMSENSE_TRIGGERUN;
01487             psm->countCorrection = -1;
01488 
01489             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERUN)) {
01490                 /* Run triggers in other package(s) this package sets off. */
01491                 rc = psmStage(psm, PSM_TRIGGERS);
01492                 if (rc) break;
01493 
01494                 /* Run triggers in this package other package(s) set off. */
01495                 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01496                 if (rc) break;
01497             }
01498 
01499             if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
01500                 rc = psmStage(psm, PSM_SCRIPT);
01501         }
01502         if (psm->goal == PSM_PKGSAVE) {
01503             /* Regenerate original header. */
01504             {   void * uh = NULL;
01505                 int_32 uht, uhc;
01506 
01507                 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01508                 {
01509                     psm->oh = headerCopyLoad(uh);
01510                     uh = hfd(uh, uht);
01511                 } else
01512                 if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
01513                 {
01514                     HeaderIterator hi;
01515                     int_32 tag, type, count;
01516                     hPTR_t ptr;
01517                     Header oh;
01518 
01519                     /* Load the original header from the blob. */
01520                     oh = headerCopyLoad(uh);
01521 
01522                     /* XXX this is headerCopy w/o headerReload() */
01523                     psm->oh = headerNew();
01524 
01525                     /*@-branchstate@*/
01526                     for (hi = headerInitIterator(oh);
01527                         headerNextIterator(hi, &tag, &type, &ptr, &count);
01528                         ptr = headerFreeData((void *)ptr, type))
01529                     {
01530                         if (ptr) (void) headerAddEntry(psm->oh, tag, type, ptr, count);
01531                     }
01532                     hi = headerFreeIterator(hi);
01533                     /*@=branchstate@*/
01534 
01535                     headerFree(oh);
01536                     uh = hfd(uh, uht);
01537                 } else {
01538                     break;
01539                 }
01540             }
01541 
01542             /* Retrieve type of payload compression. */
01543             /*@-nullstate@*/    /* FIX: psm->oh may be NULL */
01544             rc = psmStage(psm, PSM_RPMIO_FLAGS);
01545             /*@=nullstate@*/
01546 
01547             /* Write the lead section into the package. */
01548             {   int archnum = -1;
01549                 int osnum = -1;
01550                 struct rpmlead lead;
01551 
01552 #ifndef DYING
01553                 rpmGetArchInfo(NULL, &archnum);
01554                 rpmGetOsInfo(NULL, &osnum);
01555 #endif
01556 
01557                 memset(&lead, 0, sizeof(lead));
01558                 /* XXX Set package version conditioned on noDirTokens. */
01559                 lead.major = 3;
01560                 lead.minor = 0;
01561                 lead.type = RPMLEAD_BINARY;
01562                 lead.archnum = archnum;
01563                 lead.osnum = osnum;
01564                 lead.signature_type = RPMSIGTYPE_HEADERSIG;
01565 
01566                 {   char buf[256];
01567                     sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
01568                     strncpy(lead.name, buf, sizeof(lead.name));
01569                 }
01570 
01571                 rc = writeLead(psm->fd, &lead);
01572                 if (rc) {
01573                     rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
01574                          Fstrerror(psm->fd));
01575                     rc = RPMRC_FAIL;
01576                     break;
01577                 }
01578             }
01579 
01580             /* Write the signature section into the package. */
01581             {   Header sig = headerRegenSigHeader(fi->h);
01582                 rc = rpmWriteSignature(psm->fd, sig);
01583                 sig = rpmFreeSignature(sig);
01584                 if (rc) break;
01585             }
01586 
01587             /* Add remove transaction id to header. */
01588             if (psm->oh)
01589             {   int_32 tid = ts->id;
01590                 xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
01591                         RPM_INT32_TYPE, &tid, 1);
01592             }
01593 
01594             /* Write the metadata section into the package. */
01595             rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
01596             if (rc) break;
01597         }
01598         break;
01599     case PSM_PROCESS:
01600         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01601 
01602         if (psm->goal == PSM_PKGINSTALL) {
01603             struct availablePackage * alp = fi->ap;
01604             int i;
01605 
01606             if (fi->fc <= 0)                            break;
01607             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01608 
01609             for (i = 0; i < fi->fc; i++) {
01610                 uid_t uid;
01611                 gid_t gid;
01612 
01613                 uid = fi->uid;
01614                 gid = fi->gid;
01615                 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
01616                     rpmMessage(RPMMESS_WARNING,
01617                         _("user %s does not exist - using root\n"),
01618                         fi->fuser[i]);
01619                     uid = 0;
01620                     /* XXX this diddles header memory. */
01621                     fi->fmodes[i] &= ~S_ISUID;  /* turn off the suid bit */
01622                 }
01623 
01624                 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
01625                     rpmMessage(RPMMESS_WARNING,
01626                         _("group %s does not exist - using root\n"),
01627                         fi->fgroup[i]);
01628                     gid = 0;
01629                     /* XXX this diddles header memory. */
01630                     fi->fmodes[i] &= ~S_ISGID;  /* turn off the sgid bit */
01631                 }
01632                 if (fi->fuids) fi->fuids[i] = uid;
01633                 if (fi->fgids) fi->fgids[i] = gid;
01634             }
01635 
01636             /* Retrieve type of payload compression. */
01637             rc = psmStage(psm, PSM_RPMIO_FLAGS);
01638 
01639             if (alp->fd == NULL) {      /* XXX can't happen */
01640                 rc = RPMRC_FAIL;
01641                 break;
01642             }
01643             /*@-nullpass@*/     /* LCL: alp->fd != NULL here. */
01644             psm->cfd = Fdopen(fdDup(Fileno(alp->fd)), psm->rpmio_flags);
01645             /*@=nullpass@*/
01646             if (psm->cfd == NULL) {     /* XXX can't happen */
01647                 rc = RPMRC_FAIL;
01648                 break;
01649             }
01650 
01651             rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
01652                         psm->cfd, NULL, &psm->failedFile);
01653             xx = fsmTeardown(fi->fsm);
01654 
01655             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01656             xx = Fclose(psm->cfd);
01657             psm->cfd = NULL;
01658             /*@-mods@*/
01659             errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
01660             /*@=mods@*/
01661 
01662             if (!rc)
01663                 rc = psmStage(psm, PSM_COMMIT);
01664 
01665             if (rc) {
01666                 rpmError(RPMERR_CPIO,
01667                         _("unpacking of archive failed%s%s: %s\n"),
01668                         (psm->failedFile != NULL ? _(" on file ") : ""),
01669                         (psm->failedFile != NULL ? psm->failedFile : ""),
01670                         cpioStrerror(rc));
01671                 rc = RPMRC_FAIL;
01672                 break;
01673             }
01674             psm->what = RPMCALLBACK_INST_PROGRESS;
01675             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
01676             psm->total = psm->amount;
01677             xx = psmStage(psm, PSM_NOTIFY);
01678         }
01679         if (psm->goal == PSM_PKGERASE) {
01680 
01681             if (fi->fc <= 0)                            break;
01682             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01683             if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY)       break;
01684 
01685             psm->what = RPMCALLBACK_UNINST_START;
01686             psm->amount = fi->fc;       /* XXX W2DO? looks wrong. */
01687             psm->total = fi->fc;
01688             xx = psmStage(psm, PSM_NOTIFY);
01689 
01690             rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
01691                         NULL, NULL, &psm->failedFile);
01692             xx = fsmTeardown(fi->fsm);
01693 
01694             psm->what = RPMCALLBACK_UNINST_STOP;
01695             psm->amount = 0;            /* XXX W2DO? looks wrong. */
01696             psm->total = fi->fc;
01697             xx = psmStage(psm, PSM_NOTIFY);
01698 
01699         }
01700         if (psm->goal == PSM_PKGSAVE) {
01701             fileAction * actions = fi->actions;
01702             fileAction action = fi->action;
01703 
01704             fi->action = FA_COPYOUT;
01705             fi->actions = NULL;
01706 
01707             if (psm->fd == NULL) {      /* XXX can't happen */
01708                 rc = RPMRC_FAIL;
01709                 break;
01710             }
01711             /*@-nullpass@*/     /* LCL: psm->fd != NULL here. */
01712             xx = Fflush(psm->fd);
01713             psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
01714             /*@=nullpass@*/
01715             if (psm->cfd == NULL) {     /* XXX can't happen */
01716                 rc = RPMRC_FAIL;
01717                 break;
01718             }
01719 
01720             rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
01721                         NULL, &psm->failedFile);
01722             xx = fsmTeardown(fi->fsm);
01723 
01724             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01725             xx = Fclose(psm->cfd);
01726             psm->cfd = NULL;
01727             /*@-mods@*/
01728             errno = saveerrno;
01729             /*@=mods@*/
01730 
01731             fi->action = action;
01732             fi->actions = actions;
01733         }
01734         break;
01735     case PSM_POST:
01736         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01737 
01738         if (psm->goal == PSM_PKGINSTALL) {
01739             int_32 installTime = (int_32) time(NULL);
01740 
01741             if (fi->fstates != NULL && fi->fc > 0)
01742                 xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
01743                                 fi->fstates, fi->fc);
01744 
01745             xx = headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
01746                                 &installTime, 1);
01747 
01748             if (ts->transFlags & RPMTRANS_FLAG_MULTILIB) {
01749                 uint_32 multiLib, * newMultiLib, * p;
01750 
01751                 if (hge(fi->h, RPMTAG_MULTILIBS, NULL,
01752                                 (void **) &newMultiLib, NULL) &&
01753                     hge(psm->oh, RPMTAG_MULTILIBS, NULL,
01754                                 (void **) &p, NULL))
01755                 {
01756                     multiLib = *p;
01757                     multiLib |= *newMultiLib;
01758                     xx = hme(psm->oh, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01759                                       &multiLib, 1);
01760                 }
01761                 rc = mergeFiles(fi, psm->oh, fi->h);
01762                 if (rc) break;
01763             }
01764 
01765 
01766             /*
01767              * If this package has already been installed, remove it from
01768              * the database before adding the new one.
01769              */
01770             if (fi->record && !(ts->transFlags & RPMTRANS_FLAG_APPLYONLY)) {
01771                 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01772                 if (rc) break;
01773             }
01774 
01775             rc = psmStage(psm, PSM_RPMDB_ADD);
01776             if (rc) break;
01777 
01778             psm->scriptTag = RPMTAG_POSTIN;
01779             psm->progTag = RPMTAG_POSTINPROG;
01780             psm->sense = RPMSENSE_TRIGGERIN;
01781             psm->countCorrection = 0;
01782 
01783             if (!(ts->transFlags & RPMTRANS_FLAG_NOPOST)) {
01784                 rc = psmStage(psm, PSM_SCRIPT);
01785                 if (rc) break;
01786             }
01787             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERIN)) {
01788                 /* Run triggers in other package(s) this package sets off. */
01789                 rc = psmStage(psm, PSM_TRIGGERS);
01790                 if (rc) break;
01791 
01792                 /* Run triggers in this package other package(s) set off. */
01793                 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01794                 if (rc) break;
01795             }
01796 
01797             if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01798                 rc = markReplacedFiles(psm);
01799 
01800         }
01801         if (psm->goal == PSM_PKGERASE) {
01802 
01803             psm->scriptTag = RPMTAG_POSTUN;
01804             psm->progTag = RPMTAG_POSTUNPROG;
01805             psm->sense = RPMSENSE_TRIGGERPOSTUN;
01806             psm->countCorrection = -1;
01807 
01808             if (!(ts->transFlags & RPMTRANS_FLAG_NOPOSTUN)) {
01809                 rc = psmStage(psm, PSM_SCRIPT);
01810                 /* XXX WTFO? postun failures don't cause erasure failure. */
01811             }
01812 
01813             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
01814                 /* Run triggers in other package(s) this package sets off. */
01815                 rc = psmStage(psm, PSM_TRIGGERS);
01816                 if (rc) break;
01817             }
01818 
01819             if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01820                 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01821         }
01822         if (psm->goal == PSM_PKGSAVE) {
01823         }
01824 
01825         /* Restore root directory if changed. */
01826         xx = psmStage(psm, PSM_CHROOT_OUT);
01827         break;
01828     case PSM_UNDO:
01829         break;
01830     case PSM_FINI:
01831         /* Restore root directory if changed. */
01832         xx = psmStage(psm, PSM_CHROOT_OUT);
01833 
01834         if (psm->fd) {
01835             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01836             xx = Fclose(psm->fd);
01837             psm->fd = NULL;
01838             /*@-mods@*/
01839             errno = saveerrno;
01840             /*@=mods@*/
01841         }
01842 
01843         if (psm->goal == PSM_PKGSAVE) {
01844             if (!rc) {
01845                 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
01846                         (psm->pkgURL ? psm->pkgURL : "???"));
01847             }
01848         }
01849 
01850         if (rc) {
01851             if (psm->failedFile)
01852                 rpmError(RPMERR_CPIO,
01853                         _("%s failed on file %s: %s\n"),
01854                         psm->stepName, psm->failedFile, cpioStrerror(rc));
01855             else
01856                 rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
01857                         psm->stepName, cpioStrerror(rc));
01858         }
01859 
01860         if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE))
01861             fi->h = headerFree(fi->h);
01862         psm->oh = headerFree(psm->oh);
01863         psm->pkgURL = _free(psm->pkgURL);
01864         psm->rpmio_flags = _free(psm->rpmio_flags);
01865         psm->failedFile = _free(psm->failedFile);
01866 
01867         fi->fgids = _free(fi->fgids);
01868         fi->fuids = _free(fi->fuids);
01869         fi->fgroup = hfd(fi->fgroup, -1);
01870         fi->fuser = hfd(fi->fuser, -1);
01871         fi->apath = _free(fi->apath);
01872         fi->fstates = _free(fi->fstates);
01873         break;
01874 
01875     case PSM_PKGINSTALL:
01876     case PSM_PKGERASE:
01877     case PSM_PKGSAVE:
01878         psm->goal = stage;
01879         psm->rc = RPMRC_OK;
01880         psm->stepName = pkgStageString(stage);
01881 
01882         rc = psmStage(psm, PSM_INIT);
01883         if (!rc) rc = psmStage(psm, PSM_PRE);
01884         if (!rc) rc = psmStage(psm, PSM_PROCESS);
01885         if (!rc) rc = psmStage(psm, PSM_POST);
01886         xx = psmStage(psm, PSM_FINI);
01887         break;
01888     case PSM_PKGCOMMIT:
01889         break;
01890 
01891     case PSM_CREATE:
01892         break;
01893     case PSM_NOTIFY:
01894         if (ts && ts->notify) {
01895             /*@-noeffectuncon @*/ /* FIX: check rc */
01896             (void) ts->notify(fi->h, psm->what, psm->amount, psm->total,
01897                 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
01898             /*@=noeffectuncon @*/
01899         }
01900         break;
01901     case PSM_DESTROY:
01902         break;
01903     case PSM_COMMIT:
01904         if (!(ts->transFlags & RPMTRANS_FLAG_PKGCOMMIT)) break;
01905         if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
01906 
01907         rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
01908                         NULL, NULL, &psm->failedFile);
01909         xx = fsmTeardown(fi->fsm);
01910         break;
01911 
01912     case PSM_CHROOT_IN:
01913         /* Change root directory if requested and not already done. */
01914         if (ts->rootDir && !ts->chrootDone && !psm->chrootDone) {
01915             static int _loaded = 0;
01916 
01917             /*
01918              * This loads all of the name services libraries, in case we
01919              * don't have access to them in the chroot().
01920              */
01921             if (!_loaded) {
01922                 (void)getpwnam("root");
01923                 endpwent();
01924                 _loaded++;
01925             }
01926 
01927             xx = chdir("/");
01928             /*@-unrecog -superuser @*/
01929             rc = chroot(ts->rootDir);
01930             /*@=unrecog =superuser @*/
01931             psm->chrootDone = ts->chrootDone = 1;
01932             if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 1;
01933 #ifdef  DYING
01934             /*@-onlytrans@*/
01935             chroot_prefix = ts->rootDir;
01936             /*@=onlytrans@*/
01937 #endif
01938         }
01939         break;
01940     case PSM_CHROOT_OUT:
01941         /* Restore root directory if changed. */
01942         if (psm->chrootDone) {
01943             /*@-superuser @*/
01944             rc = chroot(".");
01945             /*@=superuser @*/
01946             psm->chrootDone = ts->chrootDone = 0;
01947             if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 0;
01948 #ifdef  DYING
01949             chroot_prefix = NULL;
01950 #endif
01951             xx = chdir(ts->currDir);
01952         }
01953         break;
01954     case PSM_SCRIPT:
01955         rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"),
01956                 psm->stepName, tag2sln(psm->scriptTag));
01957         rc = runInstScript(psm);
01958         break;
01959     case PSM_TRIGGERS:
01960         /* Run triggers in other package(s) this package sets off. */
01961         rc = runTriggers(psm);
01962         break;
01963     case PSM_IMMED_TRIGGERS:
01964         /* Run triggers in this package other package(s) set off. */
01965         rc = runImmedTriggers(psm);
01966         break;
01967 
01968     case PSM_RPMIO_FLAGS:
01969     {   const char * payload_compressor = NULL;
01970         char * t;
01971 
01972         if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
01973                             (void **) &payload_compressor, NULL))
01974             payload_compressor = "gzip";
01975         psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
01976         *t = '\0';
01977         t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
01978         if (!strcmp(payload_compressor, "gzip"))
01979             t = stpcpy(t, ".gzdio");
01980         if (!strcmp(payload_compressor, "bzip2"))
01981             t = stpcpy(t, ".bzdio");
01982         rc = RPMRC_OK;
01983     }   break;
01984 
01985     case PSM_RPMDB_LOAD:
01986 assert(psm->mi == NULL);
01987         psm->mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
01988                                 &fi->record, sizeof(fi->record));
01989 
01990         fi->h = rpmdbNextIterator(psm->mi);
01991         if (fi->h)
01992             fi->h = headerLink(fi->h);
01993 else {
01994 fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
01995 }
01996         psm->mi = rpmdbFreeIterator(psm->mi);
01997         rc = (fi->h ? RPMRC_OK : RPMRC_FAIL);
01998         break;
01999     case PSM_RPMDB_ADD:
02000         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
02001         if (fi->h != NULL)      /* XXX can't happen */
02002         rc = rpmdbAdd(ts->rpmdb, ts->id, fi->h);
02003         break;
02004     case PSM_RPMDB_REMOVE:
02005         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
02006         rc = rpmdbRemove(ts->rpmdb, ts->id, fi->record);
02007         break;
02008 
02009     default:
02010         break;
02011     }
02012     /*@=branchstate@*/
02013 
02014     /*@-nullstate@*/    /* FIX: psm->oh and psm->fi->h may be NULL. */
02015     return rc;
02016     /*@=nullstate@*/
02017 }

Generated on Fri Mar 10 08:19:03 2006 for rpm by  doxygen 1.4.6