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

lib/psm.c

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

Generated on Wed Mar 13 15:34:48 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002