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

# 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 }