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 "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 = MkdirP(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     char arg1_str [sizeof(int)*3+1] = "";
00855     char arg2_str [sizeof(int)*3+1] = "";
00856 
00857     if (!progArgv && !script)
00858         return 0;
00859 
00860     if (!progArgv) {
00861         argv = alloca(5 * sizeof(*argv));
00862         argv[0] = "/bin/sh";
00863         argc = 1;
00864     } else {
00865         argv = alloca((progArgc + 4) * sizeof(*argv));
00866         memcpy(argv, progArgv, progArgc * sizeof(*argv));
00867         argc = progArgc;
00868     }
00869 
00870     xx = headerNVR(h, &n, &v, &r);
00871 
00872     if (arg1 >= 0)
00873         sprintf(arg1_str, "%d", arg1);
00874     if (arg2 >= 0)
00875         sprintf(arg2_str, "%d", arg2);
00876 
00877     if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
00878         freePrefixes = 1;
00879     } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
00880         prefixes = &oldPrefix;
00881         numPrefixes = 1;
00882     } else {
00883         numPrefixes = 0;
00884     }
00885 
00886     maxPrefixLength = 0;
00887     for (i = 0; i < numPrefixes; i++) {
00888         len = strlen(prefixes[i]);
00889         if (len > maxPrefixLength) maxPrefixLength = len;
00890     }
00891     prefixBuf = alloca(maxPrefixLength + 50);
00892 
00893     if (script) {
00894         FD_t fd;
00895         /*@-branchstate@*/
00896         if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) {
00897             if (freePrefixes) free(prefixes);
00898             return 1;
00899         }
00900         /*@=branchstate@*/
00901 
00902         if (rpmIsDebug() &&
00903             (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
00904             xx = Fwrite("set -x\n", sizeof(char), 7, fd);
00905 
00906         xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
00907         xx = Fclose(fd);
00908 
00909         {   const char * sn = fn;
00910             if (!ts->chrootDone &&
00911                 !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0'))
00912             {
00913                 sn += strlen(ts->rootDir)-1;
00914             }
00915             argv[argc++] = sn;
00916         }
00917 
00918         if (*arg1_str)
00919             argv[argc++] = arg1_str;
00920         if (*arg2_str)
00921             argv[argc++] = arg2_str;
00922     }
00923 
00924     argv[argc] = NULL;
00925 
00926     if (ts->scriptFd != NULL) {
00927         if (rpmIsVerbose()) {
00928             out = fdDup(Fileno(ts->scriptFd));
00929         } else {
00930             out = Fopen("/dev/null", "w.fdio");
00931             if (Ferror(out)) {
00932                 out = fdDup(Fileno(ts->scriptFd));
00933             }
00934         }
00935     } else {
00936         out = fdDup(STDOUT_FILENO);
00937 #ifdef  DYING
00938         out = fdLink(out, "runScript persist");
00939 #endif
00940     }
00941     if (out == NULL) return 1;  /* XXX can't happen */
00942     
00943     /*@-branchstate@*/
00944     if (!(child = fork())) {
00945         const char * rootDir;
00946         int pipes[2];
00947 
00948         pipes[0] = pipes[1] = 0;
00949         /* make stdin inaccessible */
00950         xx = pipe(pipes);
00951         xx = close(pipes[1]);
00952         xx = dup2(pipes[0], STDIN_FILENO);
00953         xx = close(pipes[0]);
00954 
00955         if (ts->scriptFd != NULL) {
00956             if (Fileno(ts->scriptFd) != STDERR_FILENO)
00957                 xx = dup2(Fileno(ts->scriptFd), STDERR_FILENO);
00958             if (Fileno(out) != STDOUT_FILENO)
00959                 xx = dup2(Fileno(out), STDOUT_FILENO);
00960             /* make sure we don't close stdin/stderr/stdout by mistake! */
00961             if (Fileno(out) > STDERR_FILENO && Fileno(out) != Fileno(ts->scriptFd)) {
00962                 xx = Fclose (out);
00963             }
00964             if (Fileno(ts->scriptFd) > STDERR_FILENO) {
00965                 xx = Fclose (ts->scriptFd);
00966             }
00967         }
00968 
00969         {   const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
00970             const char *path = SCRIPT_PATH;
00971 
00972             if (ipath && ipath[5] != '%')
00973                 path = ipath;
00974             xx = doputenv(path);
00975             /*@-modobserver@*/
00976             ipath = _free(ipath);
00977             /*@=modobserver@*/
00978         }
00979 
00980         for (i = 0; i < numPrefixes; i++) {
00981             sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
00982             xx = doputenv(prefixBuf);
00983 
00984             /* backwards compatibility */
00985             if (i == 0) {
00986                 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
00987                 xx = doputenv(prefixBuf);
00988             }
00989         }
00990 
00991         dosetenv ("RPM_INSTALL_NAME", n, 1);
00992 
00993         if (*arg1_str)
00994             dosetenv ("RPM_INSTALL_ARG1", arg1_str, 1);
00995         if (*arg2_str)
00996             dosetenv ("RPM_INSTALL_ARG2", arg2_str, 1);
00997 
00998         if ( rpm_close_all() ) {
00999                 perror( "rpm_close_all" );
01000                 _exit( -1 );
01001         }
01002 
01003         if ((rootDir = ts->rootDir) != NULL)    /* XXX can't happen */
01004         switch(urlIsURL(rootDir)) {
01005         case URL_IS_PATH:
01006             rootDir += sizeof("file://") - 1;
01007             rootDir = strchr(rootDir, '/');
01008             /*@fallthrough@*/
01009         case URL_IS_UNKNOWN:
01010             if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) {
01011                 /*@-unrecog -superuser @*/
01012                 xx = chroot(rootDir);
01013                 /*@=unrecog =superuser @*/
01014             }
01015             xx = chdir("/");
01016             xx = execv(argv[0], (char *const *)argv);
01017             break;
01018         default:
01019             break;
01020         }
01021 
01022         _exit(-1);
01023         /*@notreached@*/
01024     }
01025     /*@=branchstate@*/
01026 
01027     if (waitpid(child, &status, 0) < 0) {
01028         rpmError(RPMERR_SCRIPT,
01029      _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"),
01030                  sln, n, v, r, strerror (errno));
01031         /* XXX what to do here? */
01032         rc = RPMRC_OK;
01033     } else {
01034         if (!WIFEXITED(status) || WEXITSTATUS(status)) {
01035             rpmError(RPMERR_SCRIPT,
01036      _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"),
01037                      sln, n, v, r, WEXITSTATUS(status));
01038             rc = RPMRC_FAIL;
01039         }
01040     }
01041 
01042     if (freePrefixes) prefixes = hfd(prefixes, ipt);
01043 
01044     xx = Fclose(out);   /* XXX dup'd STDOUT_FILENO */
01045     
01046     if (script) {
01047         if (!rpmIsDebug())
01048             xx = unlink(fn);
01049         fn = _free(fn);
01050     }
01051 
01052     return rc;
01053 }
01054 
01060 static rpmRC runInstScript(PSM_t psm)
01061         /*@globals rpmGlobalMacroContext,
01062                 fileSystem, internalState @*/
01063         /*@modifies psm, rpmGlobalMacroContext,
01064                 fileSystem, internalState @*/
01065 {
01066     TFI_t fi = psm->fi;
01067     HGE_t hge = fi->hge;
01068     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01069     void ** programArgv;
01070     int programArgc;
01071     const char ** argv;
01072     rpmTagType ptt, stt;
01073     const char * script;
01074     rpmRC rc = RPMRC_OK;
01075     int xx;
01076 
01077     /*
01078      * headerGetEntry() sets the data pointer to NULL if the entry does
01079      * not exist.
01080      */
01081     xx = hge(fi->h, psm->progTag, &ptt, (void **) &programArgv, &programArgc);
01082     xx = hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
01083 
01084     if (programArgv && ptt == RPM_STRING_TYPE) {
01085         argv = alloca(sizeof(char *));
01086         *argv = (const char *) programArgv;
01087     } else {
01088         argv = (const char **) programArgv;
01089     }
01090 
01091     rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), programArgc, argv,
01092                 script, psm->scriptArg, -1);
01093 
01094     programArgv = hfd(programArgv, ptt);
01095     script = hfd(script, stt);
01096     return rc;
01097 }
01098 
01107 static int handleOneTrigger(PSM_t psm, Header sourceH, Header triggeredH,
01108                         int arg2, unsigned char * triggersAlreadyRun)
01109         /*@globals rpmGlobalMacroContext,
01110                 fileSystem, internalState@*/
01111         /*@modifies psm, triggeredH, *triggersAlreadyRun, rpmGlobalMacroContext,
01112                 fileSystem, internalState @*/
01113 {
01114     const rpmTransactionSet ts = psm->ts;
01115     TFI_t fi = psm->fi;
01116     HGE_t hge = fi->hge;
01117     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01118     const char ** triggerNames;
01119     const char ** triggerEVR;
01120     const char ** triggerScripts;
01121     const char ** triggerProgs;
01122     int_32 * triggerFlags;
01123     int_32 * triggerIndices;
01124     rpmTagType tnt, tvt, tft;
01125     const char * triggerPackageName;
01126     const char * sourceName;
01127     int numTriggers;
01128     rpmRC rc = RPMRC_OK;
01129     int i;
01130     int skip;
01131     int xx;
01132 
01133     if (!(      hge(triggeredH, RPMTAG_TRIGGERNAME, &tnt, 
01134                         (void **) &triggerNames, &numTriggers) &&
01135                 hge(triggeredH, RPMTAG_TRIGGERFLAGS, &tft,
01136                         (void **) &triggerFlags, NULL) &&
01137                 hge(triggeredH, RPMTAG_TRIGGERVERSION, &tvt,
01138                         (void **) &triggerEVR, NULL))
01139         )
01140         return 0;
01141 
01142     xx = headerNVR(sourceH, &sourceName, NULL, NULL);
01143 
01144     for (i = 0; i < numTriggers; i++) {
01145         rpmTagType tit, tst, tpt;
01146 
01147         if (!(triggerFlags[i] & psm->sense)) continue;
01148         if (strcmp(triggerNames[i], sourceName)) continue;
01149 
01150         /*
01151          * For some reason, the TRIGGERVERSION stuff includes the name of
01152          * the package which the trigger is based on. We need to skip
01153          * over that here. I suspect that we'll change our minds on this
01154          * and remove that, so I'm going to just 'do the right thing'.
01155          */
01156         skip = strlen(triggerNames[i]);
01157         if (!strncmp(triggerEVR[i], triggerNames[i], skip) &&
01158             (triggerEVR[i][skip] == '-'))
01159             skip++;
01160         else
01161             skip = 0;
01162 
01163         if (!headerMatchesDepFlags(sourceH, triggerNames[i],
01164                 triggerEVR[i] + skip, triggerFlags[i]))
01165             continue;
01166 
01167         if (!(  hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
01168                        (void **) &triggerIndices, NULL) &&
01169                 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
01170                        (void **) &triggerScripts, NULL) &&
01171                 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
01172                        (void **) &triggerProgs, NULL))
01173             )
01174             continue;
01175 
01176         xx = headerNVR(triggeredH, &triggerPackageName, NULL, NULL);
01177 
01178         {   int arg1;
01179             int index;
01180 
01181             arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName);
01182             if (arg1 < 0) {
01183                 /* XXX W2DO? same as "execution of script failed" */
01184                 rc = RPMRC_FAIL;
01185             } else {
01186                 arg1 += psm->countCorrection;
01187                 index = triggerIndices[i];
01188                 if (triggersAlreadyRun == NULL ||
01189                     triggersAlreadyRun[index] == 0)
01190                 {
01191                     rc = runScript(psm, triggeredH, "%trigger", 1,
01192                             triggerProgs + index, triggerScripts[index], 
01193                             arg1, arg2);
01194                     if (triggersAlreadyRun != NULL)
01195                         triggersAlreadyRun[index] = 1;
01196                 }
01197             }
01198         }
01199 
01200         triggerIndices = hfd(triggerIndices, tit);
01201         triggerScripts = hfd(triggerScripts, tst);
01202         triggerProgs = hfd(triggerProgs, tpt);
01203 
01204         /*
01205          * Each target/source header pair can only result in a single
01206          * script being run.
01207          */
01208         break;
01209     }
01210 
01211     triggerNames = hfd(triggerNames, tnt);
01212     triggerFlags = hfd(triggerFlags, tft);
01213     triggerEVR = hfd(triggerEVR, tvt);
01214 
01215     return rc;
01216 }
01217 
01223 static int runTriggers(PSM_t psm)
01224         /*@globals rpmGlobalMacroContext,
01225                 fileSystem, internalState @*/
01226         /*@modifies psm, rpmGlobalMacroContext,
01227                 fileSystem, internalState @*/
01228 {
01229     const rpmTransactionSet ts = psm->ts;
01230     TFI_t fi = psm->fi;
01231     int numPackage;
01232     rpmRC rc = RPMRC_OK;
01233 
01234     numPackage = rpmdbCountPackages(ts->rpmdb, fi->name) + psm->countCorrection;
01235     if (numPackage < 0)
01236         return 1;
01237 
01238     {   Header triggeredH;
01239         rpmdbMatchIterator mi;
01240         int countCorrection = psm->countCorrection;
01241 
01242         psm->countCorrection = 0;
01243         mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, fi->name, 0);
01244         while((triggeredH = rpmdbNextIterator(mi)) != NULL) {
01245             rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
01246         }
01247 
01248         mi = rpmdbFreeIterator(mi);
01249         psm->countCorrection = countCorrection;
01250     }
01251 
01252     return rc;
01253 }
01254 
01260 static int runImmedTriggers(PSM_t psm)
01261         /*@globals rpmGlobalMacroContext,
01262                 fileSystem, internalState @*/
01263         /*@modifies psm, rpmGlobalMacroContext,
01264                 fileSystem, internalState @*/
01265 {
01266     const rpmTransactionSet ts = psm->ts;
01267     TFI_t fi = psm->fi;
01268     HGE_t hge = fi->hge;
01269     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01270     const char ** triggerNames;
01271     int numTriggers;
01272     int_32 * triggerIndices;
01273     rpmTagType tnt, tit;
01274     int numTriggerIndices;
01275     unsigned char * triggersRun;
01276     rpmRC rc = RPMRC_OK;
01277 
01278     if (!(      hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
01279                         (void **) &triggerNames, &numTriggers) &&
01280                 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
01281                         (void **) &triggerIndices, &numTriggerIndices))
01282         )
01283         return 0;
01284 
01285     triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
01286     memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
01287 
01288     {   Header sourceH = NULL;
01289         int i;
01290 
01291         for (i = 0; i < numTriggers; i++) {
01292             rpmdbMatchIterator mi;
01293 
01294             if (triggersRun[triggerIndices[i]] != 0) continue;
01295         
01296             mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, triggerNames[i], 0);
01297 
01298             while((sourceH = rpmdbNextIterator(mi)) != NULL) {
01299                 rc |= handleOneTrigger(psm, sourceH, fi->h, 
01300                                 rpmdbGetIteratorCount(mi),
01301                                 triggersRun);
01302             }
01303 
01304             mi = rpmdbFreeIterator(mi);
01305         }
01306     }
01307     triggerIndices = hfd(triggerIndices, tit);
01308     triggerNames = hfd(triggerNames, tnt);
01309     return rc;
01310 }
01311 
01312 /*@observer@*/ static const char *const pkgStageString(pkgStage a)
01313         /*@*/
01314 {
01315     switch(a) {
01316     case PSM_UNKNOWN:           return "unknown";
01317 
01318     case PSM_PKGINSTALL:        return "  install";
01319     case PSM_PKGERASE:          return "    erase";
01320     case PSM_PKGCOMMIT:         return "   commit";
01321     case PSM_PKGSAVE:           return "repackage";
01322 
01323     case PSM_INIT:              return "init";
01324     case PSM_PRE:               return "pre";
01325     case PSM_PROCESS:           return "process";
01326     case PSM_POST:              return "post";
01327     case PSM_UNDO:              return "undo";
01328     case PSM_FINI:              return "fini";
01329 
01330     case PSM_CREATE:            return "create";
01331     case PSM_NOTIFY:            return "notify";
01332     case PSM_DESTROY:           return "destroy";
01333     case PSM_COMMIT:            return "commit";
01334 
01335     case PSM_CHROOT_IN:         return "chrootin";
01336     case PSM_CHROOT_OUT:        return "chrootout";
01337     case PSM_SCRIPT:            return "script";
01338     case PSM_TRIGGERS:          return "triggers";
01339     case PSM_IMMED_TRIGGERS:    return "immedtriggers";
01340 
01341     case PSM_RPMIO_FLAGS:       return "rpmioflags";
01342 
01343     case PSM_RPMDB_LOAD:        return "rpmdbload";
01344     case PSM_RPMDB_ADD:         return "rpmdbadd";
01345     case PSM_RPMDB_REMOVE:      return "rpmdbremove";
01346 
01347     default:                    return "???";
01348     }
01349     /*@noteached@*/
01350 }
01351 
01356 int psmStage(PSM_t psm, pkgStage stage)
01357 {
01358     const rpmTransactionSet ts = psm->ts;
01359     TFI_t fi = psm->fi;
01360     HGE_t hge = fi->hge;
01361     HME_t hme = fi->hme;
01362     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01363     rpmRC rc = psm->rc;
01364     int saveerrno;
01365     int xx;
01366 
01367     /*@-branchstate@*/
01368     switch (stage) {
01369     case PSM_UNKNOWN:
01370         break;
01371     case PSM_INIT:
01372         rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"),
01373                 psm->stepName, fi->name, fi->version, fi->release,
01374                 fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST));
01375 
01376         /*
01377          * When we run scripts, we pass an argument which is the number of 
01378          * versions of this package that will be installed when we are
01379          * finished.
01380          */
01381         psm->npkgs_installed = rpmdbCountPackages(ts->rpmdb, fi->name);
01382         if (psm->npkgs_installed < 0) {
01383             rc = RPMRC_FAIL;
01384             break;
01385         }
01386 
01387         if (psm->goal == PSM_PKGINSTALL) {
01388             psm->scriptArg = psm->npkgs_installed + 1;
01389 
01390 assert(psm->mi == NULL);
01391             psm->mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, fi->name, 0);
01392             xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION,
01393                         RPMMIRE_DEFAULT, fi->version);
01394             xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE,
01395                         RPMMIRE_DEFAULT, fi->release);
01396 
01397             while ((psm->oh = rpmdbNextIterator(psm->mi))) {
01398                 fi->record = rpmdbGetIteratorOffset(psm->mi);
01399                 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB)
01400                     psm->oh = headerCopy(psm->oh);
01401                 else
01402                     psm->oh = NULL;
01403                 /*@loopbreak@*/ break;
01404             }
01405             psm->mi = rpmdbFreeIterator(psm->mi);
01406             rc = RPMRC_OK;
01407 
01408             if (fi->fc > 0 && fi->fstates == NULL) {
01409                 fi->fstates = xmalloc(sizeof(*fi->fstates) * fi->fc);
01410                 memset(fi->fstates, RPMFILE_STATE_NORMAL, fi->fc);
01411             }
01412 
01413             if (fi->fc <= 0)                            break;
01414             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01415         
01416             /*
01417              * Old format relocateable packages need the entire default
01418              * prefix stripped to form the cpio list, while all other packages
01419              * need the leading / stripped.
01420              */
01421             {   const char * p;
01422                 rc = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
01423                 fi->striplen = (rc ? strlen(p) + 1 : 1); 
01424             }
01425             fi->mapflags =
01426                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01427         
01428             if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
01429                 buildOrigFileList(fi->h, &fi->apath, NULL);
01430             else
01431                 rpmBuildFileList(fi->h, &fi->apath, NULL);
01432         
01433             if (fi->fuser == NULL)
01434                 xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
01435                                 (void **) &fi->fuser, NULL);
01436             if (fi->fgroup == NULL)
01437                 xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
01438                                 (void **) &fi->fgroup, NULL);
01439             if (fi->fuids == NULL)
01440                 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01441             if (fi->fgids == NULL)
01442                 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01443             rc = RPMRC_OK;
01444         }
01445         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
01446             psm->scriptArg = psm->npkgs_installed - 1;
01447         
01448             /* Retrieve installed header. */
01449             rc = psmStage(psm, PSM_RPMDB_LOAD);
01450         }
01451         if (psm->goal == PSM_PKGSAVE) {
01452             /* Open output package for writing. */
01453             {   const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
01454                 const char * pkgbn =
01455                         headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
01456 
01457                 bfmt = _free(bfmt);
01458                 psm->pkgURL = rpmGenPath("%{?_repackage_root:%{_repackage_root}}",
01459                                          "%{?_repackage_dir:%{_repackage_dir}}",
01460                                         pkgbn);
01461                 pkgbn = _free(pkgbn);
01462                 (void) urlPath(psm->pkgURL, &psm->pkgfn);
01463                 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
01464                 if (psm->fd == NULL || Ferror(psm->fd)) {
01465                     rc = RPMRC_FAIL;
01466                     break;
01467                 }
01468             }
01469         }
01470         break;
01471     case PSM_PRE:
01472         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01473 
01474         /* Change root directory if requested and not already done. */
01475         rc = psmStage(psm, PSM_CHROOT_IN);
01476 
01477         if (psm->goal == PSM_PKGINSTALL) {
01478             psm->scriptTag = RPMTAG_PREIN;
01479             psm->progTag = RPMTAG_PREINPROG;
01480 
01481             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
01482                 /* XXX FIXME: implement %triggerprein. */
01483             }
01484 
01485             if (!(ts->transFlags & RPMTRANS_FLAG_NOPRE)) {
01486                 rc = psmStage(psm, PSM_SCRIPT);
01487                 if (rc) {
01488                     rpmError(RPMERR_SCRIPT,
01489                         _("%s: %s scriptlet failed (%d), skipping %s-%s-%s\n"),
01490                         psm->stepName, tag2sln(psm->scriptTag), rc,
01491                         fi->name, fi->version, fi->release);
01492                     break;
01493                 }
01494             }
01495         }
01496 
01497         if (psm->goal == PSM_PKGERASE) {
01498             psm->scriptTag = RPMTAG_PREUN;
01499             psm->progTag = RPMTAG_PREUNPROG;
01500             psm->sense = RPMSENSE_TRIGGERUN;
01501             psm->countCorrection = -1;
01502 
01503             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERUN)) {
01504                 /* Run triggers in other package(s) this package sets off. */
01505                 rc = psmStage(psm, PSM_TRIGGERS);
01506                 if (rc) break;
01507 
01508                 /* Run triggers in this package other package(s) set off. */
01509                 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01510                 if (rc) break;
01511             }
01512 
01513             if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
01514                 rc = psmStage(psm, PSM_SCRIPT);
01515         }
01516         if (psm->goal == PSM_PKGSAVE) {
01517             /* Regenerate original header. */
01518             {   void * uh = NULL;
01519                 int_32 uht, uhc;
01520 
01521                 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01522                 {
01523                     psm->oh = headerCopyLoad(uh);
01524                     uh = hfd(uh, uht);
01525                 } else
01526                 if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
01527                 {
01528                     HeaderIterator hi;
01529                     int_32 tag, type, count;
01530                     hPTR_t ptr;
01531                     Header oh;
01532 
01533                     /* Load the original header from the blob. */
01534                     oh = headerCopyLoad(uh);
01535 
01536                     /* XXX this is headerCopy w/o headerReload() */
01537                     psm->oh = headerNew();
01538 
01539                     /*@-branchstate@*/
01540                     for (hi = headerInitIterator(oh);
01541                         headerNextIterator(hi, &tag, &type, &ptr, &count);
01542                         ptr = headerFreeData((void *)ptr, type))
01543                     {
01544                         if (ptr) (void) headerAddEntry(psm->oh, tag, type, ptr, count);
01545                     }
01546                     hi = headerFreeIterator(hi);
01547                     /*@=branchstate@*/
01548 
01549                     headerFree(oh);
01550                     uh = hfd(uh, uht);
01551                 } else {
01552                     break;
01553                 }
01554             }
01555 
01556             /* Retrieve type of payload compression. */
01557             /*@-nullstate@*/    /* FIX: psm->oh may be NULL */
01558             rc = psmStage(psm, PSM_RPMIO_FLAGS);
01559             /*@=nullstate@*/
01560 
01561             /* Write the lead section into the package. */
01562             {   int archnum = -1;
01563                 int osnum = -1;
01564                 struct rpmlead lead;
01565 
01566 #ifndef DYING
01567                 rpmGetArchInfo(NULL, &archnum);
01568                 rpmGetOsInfo(NULL, &osnum);
01569 #endif
01570 
01571                 memset(&lead, 0, sizeof(lead));
01572                 /* XXX Set package version conditioned on noDirTokens. */
01573                 lead.major = 3;
01574                 lead.minor = 0;
01575                 lead.type = RPMLEAD_BINARY;
01576                 lead.archnum = archnum;
01577                 lead.osnum = osnum;
01578                 lead.signature_type = RPMSIGTYPE_HEADERSIG;
01579 
01580                 {   char buf[256];
01581                     sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
01582                     strncpy(lead.name, buf, sizeof(lead.name));
01583                 }
01584 
01585                 rc = writeLead(psm->fd, &lead);
01586                 if (rc) {
01587                     rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
01588                          Fstrerror(psm->fd));
01589                     rc = RPMRC_FAIL;
01590                     break;
01591                 }
01592             }
01593 
01594             /* Write the signature section into the package. */
01595             {   Header sig = headerRegenSigHeader(fi->h);
01596                 rc = rpmWriteSignature(psm->fd, sig);
01597                 sig = rpmFreeSignature(sig);
01598                 if (rc) break;
01599             }
01600 
01601             /* Add remove transaction id to header. */
01602             if (psm->oh)
01603             {   int_32 tid = ts->id;
01604                 xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
01605                         RPM_INT32_TYPE, &tid, 1);
01606             }
01607 
01608             /* Write the metadata section into the package. */
01609             rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
01610             if (rc) break;
01611         }
01612         break;
01613     case PSM_PROCESS:
01614         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01615 
01616         if (psm->goal == PSM_PKGINSTALL) {
01617             struct availablePackage * alp = fi->ap;
01618             int i;
01619 
01620             if (fi->fc <= 0)                            break;
01621             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01622 
01623             for (i = 0; i < fi->fc; i++) {
01624                 uid_t uid;
01625                 gid_t gid;
01626 
01627                 uid = fi->uid;
01628                 gid = fi->gid;
01629                 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
01630                     rpmMessage(RPMMESS_WARNING,
01631                         _("user %s does not exist - using root\n"),
01632                         fi->fuser[i]);
01633                     uid = 0;
01634                     /* XXX this diddles header memory. */
01635                     fi->fmodes[i] &= ~S_ISUID;  /* turn off the suid bit */
01636                 }
01637 
01638                 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
01639                     rpmMessage(RPMMESS_WARNING,
01640                         _("group %s does not exist - using root\n"),
01641                         fi->fgroup[i]);
01642                     gid = 0;
01643                     /* XXX this diddles header memory. */
01644                     fi->fmodes[i] &= ~S_ISGID;  /* turn off the sgid bit */
01645                 }
01646                 if (fi->fuids) fi->fuids[i] = uid;
01647                 if (fi->fgids) fi->fgids[i] = gid;
01648             }
01649 
01650             /* Retrieve type of payload compression. */
01651             rc = psmStage(psm, PSM_RPMIO_FLAGS);
01652 
01653             if (alp->fd == NULL) {      /* XXX can't happen */
01654                 rc = RPMRC_FAIL;
01655                 break;
01656             }
01657             /*@-nullpass@*/     /* LCL: alp->fd != NULL here. */
01658             psm->cfd = Fdopen(fdDup(Fileno(alp->fd)), psm->rpmio_flags);
01659             /*@=nullpass@*/
01660             if (psm->cfd == NULL) {     /* XXX can't happen */
01661                 rc = RPMRC_FAIL;
01662                 break;
01663             }
01664 
01665             rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
01666                         psm->cfd, NULL, &psm->failedFile);
01667             xx = fsmTeardown(fi->fsm);
01668 
01669             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01670             xx = Fclose(psm->cfd);
01671             psm->cfd = NULL;
01672             /*@-mods@*/
01673             errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
01674             /*@=mods@*/
01675 
01676             if (!rc)
01677                 rc = psmStage(psm, PSM_COMMIT);
01678 
01679             if (rc) {
01680                 rpmError(RPMERR_CPIO,
01681                         _("unpacking of archive failed%s%s: %s\n"),
01682                         (psm->failedFile != NULL ? _(" on file ") : ""),
01683                         (psm->failedFile != NULL ? psm->failedFile : ""),
01684                         cpioStrerror(rc));
01685                 rc = RPMRC_FAIL;
01686 
01687                 /* XXX notify callback on error. */
01688                 psm->what = RPMCALLBACK_UNPACK_ERROR;
01689                 psm->amount = 0;
01690                 psm->total = 0;
01691                 xx = psmStage(psm, PSM_NOTIFY);
01692 
01693                 break;
01694             }
01695             psm->what = RPMCALLBACK_INST_PROGRESS;
01696             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
01697             psm->total = psm->amount;
01698             xx = psmStage(psm, PSM_NOTIFY);
01699         }
01700         if (psm->goal == PSM_PKGERASE) {
01701 
01702             if (fi->fc <= 0)                            break;
01703             if (ts->transFlags & RPMTRANS_FLAG_JUSTDB)  break;
01704             if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY)       break;
01705 
01706             psm->what = RPMCALLBACK_UNINST_START;
01707             psm->amount = fi->fc;       /* XXX W2DO? looks wrong. */
01708             psm->total = fi->fc;
01709             xx = psmStage(psm, PSM_NOTIFY);
01710 
01711             rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
01712                         NULL, NULL, &psm->failedFile);
01713             xx = fsmTeardown(fi->fsm);
01714 
01715             psm->what = RPMCALLBACK_UNINST_STOP;
01716             psm->amount = 0;            /* XXX W2DO? looks wrong. */
01717             psm->total = fi->fc;
01718             xx = psmStage(psm, PSM_NOTIFY);
01719 
01720         }
01721         if (psm->goal == PSM_PKGSAVE) {
01722             fileAction * actions = fi->actions;
01723             fileAction action = fi->action;
01724 
01725             fi->action = FA_COPYOUT;
01726             fi->actions = NULL;
01727 
01728             if (psm->fd == NULL) {      /* XXX can't happen */
01729                 rc = RPMRC_FAIL;
01730                 break;
01731             }
01732             /*@-nullpass@*/     /* LCL: psm->fd != NULL here. */
01733             xx = Fflush(psm->fd);
01734             psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
01735             /*@=nullpass@*/
01736             if (psm->cfd == NULL) {     /* XXX can't happen */
01737                 rc = RPMRC_FAIL;
01738                 break;
01739             }
01740 
01741             rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
01742                         NULL, &psm->failedFile);
01743             xx = fsmTeardown(fi->fsm);
01744 
01745             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01746             xx = Fclose(psm->cfd);
01747             psm->cfd = NULL;
01748             /*@-mods@*/
01749             errno = saveerrno;
01750             /*@=mods@*/
01751 
01752             fi->action = action;
01753             fi->actions = actions;
01754         }
01755         break;
01756     case PSM_POST:
01757         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
01758 
01759         if (psm->goal == PSM_PKGINSTALL) {
01760             int_32 installTime = (int_32) time(NULL);
01761 
01762             if (fi->fstates != NULL && fi->fc > 0)
01763                 xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
01764                                 fi->fstates, fi->fc);
01765 
01766             xx = headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
01767                                 &installTime, 1);
01768 
01769             if (ts->transFlags & RPMTRANS_FLAG_MULTILIB) {
01770                 uint_32 multiLib, * newMultiLib, * p;
01771 
01772                 if (hge(fi->h, RPMTAG_MULTILIBS, NULL,
01773                                 (void **) &newMultiLib, NULL) &&
01774                     hge(psm->oh, RPMTAG_MULTILIBS, NULL,
01775                                 (void **) &p, NULL))
01776                 {
01777                     multiLib = *p;
01778                     multiLib |= *newMultiLib;
01779                     xx = hme(psm->oh, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01780                                       &multiLib, 1);
01781                 }
01782                 rc = mergeFiles(fi, psm->oh, fi->h);
01783                 if (rc) break;
01784             }
01785 
01786 
01787             /*
01788              * If this package has already been installed, remove it from
01789              * the database before adding the new one.
01790              */
01791             if (fi->record && !(ts->transFlags & RPMTRANS_FLAG_APPLYONLY)) {
01792                 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01793                 if (rc) break;
01794             }
01795 
01796             rc = psmStage(psm, PSM_RPMDB_ADD);
01797             if (rc) break;
01798 
01799             psm->scriptTag = RPMTAG_POSTIN;
01800             psm->progTag = RPMTAG_POSTINPROG;
01801             psm->sense = RPMSENSE_TRIGGERIN;
01802             psm->countCorrection = 0;
01803 
01804             if (!(ts->transFlags & RPMTRANS_FLAG_NOPOST)) {
01805                 rc = psmStage(psm, PSM_SCRIPT);
01806                 if (rc) break;
01807             }
01808             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERIN)) {
01809                 /* Run triggers in other package(s) this package sets off. */
01810                 rc = psmStage(psm, PSM_TRIGGERS);
01811                 if (rc) break;
01812 
01813                 /* Run triggers in this package other package(s) set off. */
01814                 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01815                 if (rc) break;
01816             }
01817 
01818             if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01819                 rc = markReplacedFiles(psm);
01820 
01821         }
01822         if (psm->goal == PSM_PKGERASE) {
01823 
01824             psm->scriptTag = RPMTAG_POSTUN;
01825             psm->progTag = RPMTAG_POSTUNPROG;
01826             psm->sense = RPMSENSE_TRIGGERPOSTUN;
01827             psm->countCorrection = -1;
01828 
01829             if (!(ts->transFlags & RPMTRANS_FLAG_NOPOSTUN)) {
01830                 rc = psmStage(psm, PSM_SCRIPT);
01831                 /* XXX WTFO? postun failures don't cause erasure failure. */
01832             }
01833 
01834             if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
01835                 /* Run triggers in other package(s) this package sets off. */
01836                 rc = psmStage(psm, PSM_TRIGGERS);
01837                 if (rc) break;
01838             }
01839 
01840             if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01841                 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01842         }
01843         if (psm->goal == PSM_PKGSAVE) {
01844         }
01845 
01846         /* Restore root directory if changed. */
01847         xx = psmStage(psm, PSM_CHROOT_OUT);
01848         break;
01849     case PSM_UNDO:
01850         break;
01851     case PSM_FINI:
01852         /* Restore root directory if changed. */
01853         xx = psmStage(psm, PSM_CHROOT_OUT);
01854 
01855         if (psm->fd) {
01856             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
01857             xx = Fclose(psm->fd);
01858             psm->fd = NULL;
01859             /*@-mods@*/
01860             errno = saveerrno;
01861             /*@=mods@*/
01862         }
01863 
01864         if (psm->goal == PSM_PKGSAVE) {
01865             if (!rc) {
01866                 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
01867                         (psm->pkgURL ? psm->pkgURL : "???"));
01868             }
01869         }
01870 
01871         if (rc) {
01872             if (psm->failedFile)
01873                 rpmError(RPMERR_CPIO,
01874                         _("%s failed on file %s: %s\n"),
01875                         psm->stepName, psm->failedFile, cpioStrerror(rc));
01876             else
01877                 rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
01878                         psm->stepName, cpioStrerror(rc));
01879 
01880             /* XXX notify callback on error. */
01881             psm->what = RPMCALLBACK_CPIO_ERROR;
01882             psm->amount = 0;
01883             psm->total = 0;
01884             xx = psmStage(psm, PSM_NOTIFY);
01885         }
01886 
01887         if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE))
01888             fi->h = headerFree(fi->h);
01889         psm->oh = headerFree(psm->oh);
01890         psm->pkgURL = _free(psm->pkgURL);
01891         psm->rpmio_flags = _free(psm->rpmio_flags);
01892         psm->failedFile = _free(psm->failedFile);
01893 
01894         fi->fgids = _free(fi->fgids);
01895         fi->fuids = _free(fi->fuids);
01896         fi->fgroup = hfd(fi->fgroup, -1);
01897         fi->fuser = hfd(fi->fuser, -1);
01898         fi->apath = _free(fi->apath);
01899         fi->fstates = _free(fi->fstates);
01900         break;
01901 
01902     case PSM_PKGINSTALL:
01903     case PSM_PKGERASE:
01904     case PSM_PKGSAVE:
01905         psm->goal = stage;
01906         psm->rc = RPMRC_OK;
01907         psm->stepName = pkgStageString(stage);
01908 
01909         rc = psmStage(psm, PSM_INIT);
01910         if (!rc) rc = psmStage(psm, PSM_PRE);
01911         if (!rc) rc = psmStage(psm, PSM_PROCESS);
01912         if (!rc) rc = psmStage(psm, PSM_POST);
01913         xx = psmStage(psm, PSM_FINI);
01914         break;
01915     case PSM_PKGCOMMIT:
01916         break;
01917 
01918     case PSM_CREATE:
01919         break;
01920     case PSM_NOTIFY:
01921         if (ts && ts->notify) {
01922             /*@-noeffectuncon @*/ /* FIX: check rc */
01923             (void) ts->notify(fi->h, psm->what, psm->amount, psm->total,
01924                 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
01925             /*@=noeffectuncon @*/
01926         }
01927         break;
01928     case PSM_DESTROY:
01929         break;
01930     case PSM_COMMIT:
01931         if (!(ts->transFlags & RPMTRANS_FLAG_PKGCOMMIT)) break;
01932         if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
01933 
01934         rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
01935                         NULL, NULL, &psm->failedFile);
01936         xx = fsmTeardown(fi->fsm);
01937         break;
01938 
01939     case PSM_CHROOT_IN:
01940         /* Change root directory if requested and not already done. */
01941         if (ts->rootDir && !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0') &&
01942             !ts->chrootDone && !psm->chrootDone) {
01943             static int _loaded = 0;
01944 
01945             /*
01946              * This loads all of the name services libraries, in case we
01947              * don't have access to them in the chroot().
01948              */
01949             if (!_loaded) {
01950                 (void)getpwnam("root");
01951                 endpwent();
01952                 _loaded++;
01953             }
01954 
01955             xx = chdir("/");
01956             /*@-unrecog -superuser @*/
01957             rc = chroot(ts->rootDir);
01958             /*@=unrecog =superuser @*/
01959             psm->chrootDone = ts->chrootDone = 1;
01960             if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 1;
01961 #ifdef  DYING
01962             /*@-onlytrans@*/
01963             chroot_prefix = ts->rootDir;
01964             /*@=onlytrans@*/
01965 #endif
01966         }
01967         break;
01968     case PSM_CHROOT_OUT:
01969         /* Restore root directory if changed. */
01970         if (psm->chrootDone) {
01971             /*@-superuser @*/
01972             rc = chroot(".");
01973             /*@=superuser @*/
01974             psm->chrootDone = ts->chrootDone = 0;
01975             if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 0;
01976 #ifdef  DYING
01977             chroot_prefix = NULL;
01978 #endif
01979             xx = chdir(ts->currDir);
01980         }
01981         break;
01982     case PSM_SCRIPT:
01983         rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"),
01984                 psm->stepName, tag2sln(psm->scriptTag));
01985         rc = runInstScript(psm);
01986         break;
01987     case PSM_TRIGGERS:
01988         /* Run triggers in other package(s) this package sets off. */
01989         rc = runTriggers(psm);
01990         break;
01991     case PSM_IMMED_TRIGGERS:
01992         /* Run triggers in this package other package(s) set off. */
01993         rc = runImmedTriggers(psm);
01994         break;
01995 
01996     case PSM_RPMIO_FLAGS:
01997     {   const char * payload_compressor = NULL;
01998         char * t;
01999 
02000         if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
02001                             (void **) &payload_compressor, NULL))
02002             payload_compressor = "gzip";
02003         psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
02004         *t = '\0';
02005         t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
02006         if (!strcmp(payload_compressor, "gzip"))
02007             t = stpcpy(t, ".gzdio");
02008         if (!strcmp(payload_compressor, "bzip2"))
02009             t = stpcpy(t, ".bzdio");
02010         rc = RPMRC_OK;
02011     }   break;
02012 
02013     case PSM_RPMDB_LOAD:
02014 assert(psm->mi == NULL);
02015         psm->mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
02016                                 &fi->record, sizeof(fi->record));
02017 
02018         fi->h = rpmdbNextIterator(psm->mi);
02019         if (fi->h)
02020             fi->h = headerLink(fi->h);
02021 else {
02022 fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
02023 }
02024         psm->mi = rpmdbFreeIterator(psm->mi);
02025         rc = (fi->h ? RPMRC_OK : RPMRC_FAIL);
02026         break;
02027     case PSM_RPMDB_ADD:
02028         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
02029         if (fi->h != NULL)      /* XXX can't happen */
02030         rc = rpmdbAdd(ts->rpmdb, ts->id, fi->h);
02031 #if HAVE_SYSLOG_H
02032         syslog( LOG_NOTICE, "%s-%u:%s-%s installed\n", fi->name, (-1 == fi->epoch) ? 0 : fi->epoch, fi->version, fi->release);
02033 #endif
02034         break;
02035     case PSM_RPMDB_REMOVE:
02036         if (ts->transFlags & RPMTRANS_FLAG_TEST)        break;
02037         rc = rpmdbRemove(ts->rpmdb, ts->id, fi->record);
02038 #if HAVE_SYSLOG_H
02039         syslog( LOG_NOTICE, "%s-%u:%s-%s removed\n", fi->name, (-1 == fi->epoch) ? 0 : fi->epoch, fi->version, fi->release);
02040 #endif
02041         break;
02042 
02043     default:
02044         break;
02045     }
02046     /*@=branchstate@*/
02047 
02048     /*@-nullstate@*/    /* FIX: psm->oh and psm->fi->h may be NULL. */
02049     return rc;
02050     /*@=nullstate@*/
02051 }

Generated on Sun Feb 2 23:32:02 2003 for rpm by doxygen1.2.18