1 /** \ingroup rpmtrans payload
3 * Package state machine to handle a package from a transaction set.
13 #include "rpmlead.h" /* writeLead proto */
14 #include "signature.h" /* signature constants */
18 /*@access Header @*/ /* compared with NULL */
19 /*@access rpmTransactionSet @*/ /* compared with NULL */
20 /*@access rpmdbMatchIterator @*/ /* compared with NULL */
21 /*@access TFI_t @*/ /* compared with NULL */
22 /*@access FSM_t @*/ /* compared with NULL */
23 /*@access PSM_t @*/ /* compared with NULL */
24 /*@access FD_t @*/ /* compared with NULL */
26 extern int _fsm_debug;
29 * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
30 * @param this memory to free
33 static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) {
34 if (this) free((void *)this);
38 int rpmVersionCompare(Header first, Header second)
40 const char * one, * two;
41 int_32 * epochOne, * epochTwo;
44 if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
46 if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo,
50 if (epochOne && !epochTwo)
52 else if (!epochOne && epochTwo)
54 else if (epochOne && epochTwo) {
55 if (*epochOne < *epochTwo)
57 else if (*epochOne > *epochTwo)
61 headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
62 headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
64 rc = rpmvercmp(one, two);
68 headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
69 headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
71 return rpmvercmp(one, two);
74 void loadFi(Header h, TFI_t fi)
86 /* XXX avoid gcc noise on pointer (4th arg) cast(s) */
87 hge = (fi->type == TR_ADDED)
88 ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry;
91 fi->hfd = hfd = headerFreeData;
93 if (h && fi->h == NULL) fi->h = headerLink(h);
95 /* Duplicate name-version-release so that headers can be free'd. */
96 hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL);
97 fi->name = xstrdup(fi->name);
98 hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL);
99 fi->version = xstrdup(fi->version);
100 hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL);
101 fi->release = xstrdup(fi->release);
103 /* -1 means not found */
104 rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL);
105 fi->epoch = (rc ? *uip : -1);
106 /* 0 means unknown */
107 rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL);
108 fi->archiveSize = (rc ? *uip : 0);
110 if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) {
116 hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
117 hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
118 hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL);
119 hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL);
120 hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL);
121 hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL);
123 fi->action = FA_UNKNOWN;
126 /* actions is initialized earlier for added packages */
127 if (fi->actions == NULL)
128 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
132 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
133 hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
134 hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
135 hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL);
136 hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL);
138 /* 0 makes for noops */
139 fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
143 fi->mapflags = CPIO_MAP_ABSOLUTE | CPIO_MAP_ADDDOT | CPIO_MAP_PATH | CPIO_MAP_MODE;
144 hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
145 hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
146 fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)),
147 fi->fsizes, fi->fc * sizeof(*fi->fsizes));
148 fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)),
149 fi->fflags, fi->fc * sizeof(*fi->fflags));
150 fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)),
151 fi->fmodes, fi->fc * sizeof(*fi->fmodes));
152 /* XXX there's a tedious segfault here for some version(s) of rpm */
154 fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)),
155 fi->fstates, fi->fc * sizeof(*fi->fstates));
157 fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates));
158 fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)),
159 fi->dil, fi->fc * sizeof(*fi->dil));
166 for (i = 0; i < fi->dc; i++) {
167 if ((len = strlen(fi->dnl[i])) > fi->dnlmax)
172 for (i = 0; i < fi->fc; i++) {
173 if ((len = strlen(fi->bnl[i])) > fi->bnlmax)
183 void freeFi(TFI_t fi)
185 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
187 fi->name = _free(fi->name);
188 fi->version = _free(fi->version);
189 fi->release = _free(fi->release);
190 fi->actions = _free(fi->actions);
191 fi->replacedSizes = _free(fi->replacedSizes);
192 fi->replaced = _free(fi->replaced);
194 fi->bnl = hfd(fi->bnl, -1);
195 fi->dnl = hfd(fi->dnl, -1);
196 fi->obnl = hfd(fi->obnl, -1);
197 fi->odnl = hfd(fi->odnl, -1);
198 fi->flinks = hfd(fi->flinks, -1);
199 fi->fmd5s = hfd(fi->fmd5s, -1);
200 fi->fuser = hfd(fi->fuser, -1);
201 fi->fgroup = hfd(fi->fgroup, -1);
202 fi->flangs = hfd(fi->flangs, -1);
204 fi->apath = _free(fi->apath);
205 fi->fuids = _free(fi->fuids);
206 fi->fgids = _free(fi->fgids);
207 fi->fmapflags = _free(fi->fmapflags);
209 fi->fsm = freeFSM(fi->fsm);
215 fi->fsizes = hfd(fi->fsizes, -1);
216 fi->fflags = hfd(fi->fflags, -1);
217 fi->fmodes = hfd(fi->fmodes, -1);
218 fi->fstates = hfd(fi->fstates, -1);
219 fi->dil = hfd(fi->dil, -1);
223 headerFree(fi->h); fi->h = NULL;
227 /*@observer@*/ const char *const fiTypeString(TFI_t fi) {
229 case TR_ADDED: return " install";
230 case TR_REMOVED: return " erase";
231 default: return "???";
237 * Macros to be defined from per-header tag values.
238 * @todo Should other macros be added from header when installing a package?
240 static struct tagMacro {
241 const char * macroname; /*!< Macro name to define. */
242 int tag; /*!< Header tag to use for value. */
244 { "name", RPMTAG_NAME },
245 { "version", RPMTAG_VERSION },
246 { "release", RPMTAG_RELEASE },
248 { "epoch", RPMTAG_EPOCH },
254 * Define per-header macros.
258 static int rpmInstallLoadMacros(TFI_t fi, Header h)
260 HGE_t hge = (HGE_t)fi->hge;
261 struct tagMacro *tagm;
269 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
270 if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
274 sprintf(numbuf, "%d", *body.i32p);
275 addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
277 case RPM_STRING_TYPE:
278 addMacro(NULL, tagm->macroname, NULL, body.ptr, -1);
286 * Copy file data from h to newH.
287 * @param h header from
288 * @param newH header to
289 * @param actions array of file dispositions
290 * @return 0 on success, 1 on failure
292 static int mergeFiles(TFI_t fi, Header h, Header newH)
294 HGE_t hge = (HGE_t)fi->hge;
296 fileAction * actions = fi->actions;
300 int_32 dirNamesCount, dirCount;
301 void * data, * newdata;
302 int_32 * dirIndexes, * newDirIndexes;
303 uint_32 * fileSizes, fileSize;
304 const char ** dirNames;
305 const char ** newDirNames;
306 static int_32 mergeTags[] = {
316 RPMTAG_FILEGROUPNAME,
317 RPMTAG_FILEVERIFYFLAGS,
324 static int_32 requireTags[] = {
325 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
326 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
327 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS
330 hge(h, RPMTAG_SIZE, NULL, (void **) &fileSizes, NULL);
331 fileSize = *fileSizes;
332 hge(newH, RPMTAG_FILESIZES, NULL, (void **) &fileSizes, &count);
333 for (i = 0, fc = 0; i < count; i++)
334 if (actions[i] != FA_SKIPMULTILIB) {
336 fileSize += fileSizes[i];
338 headerModifyEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE, &fileSize, 1);
340 for (i = 0; mergeTags[i]; i++) {
341 if (!hge(newH, mergeTags[i], &type, (void **) &data, &count))
346 newdata = xmalloc(fc * sizeof(int_8));
347 for (j = 0, k = 0; j < count; j++)
348 if (actions[j] != FA_SKIPMULTILIB)
349 ((int_8 *) newdata)[k++] = ((int_8 *) data)[j];
350 headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
354 newdata = xmalloc(fc * sizeof(int_16));
355 for (j = 0, k = 0; j < count; j++)
356 if (actions[j] != FA_SKIPMULTILIB)
357 ((int_16 *) newdata)[k++] = ((int_16 *) data)[j];
358 headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
362 newdata = xmalloc(fc * sizeof(int_32));
363 for (j = 0, k = 0; j < count; j++)
364 if (actions[j] != FA_SKIPMULTILIB)
365 ((int_32 *) newdata)[k++] = ((int_32 *) data)[j];
366 headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
369 case RPM_STRING_ARRAY_TYPE:
370 newdata = xmalloc(fc * sizeof(char *));
371 for (j = 0, k = 0; j < count; j++)
372 if (actions[j] != FA_SKIPMULTILIB)
373 ((char **) newdata)[k++] = ((char **) data)[j];
374 headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
378 rpmError(RPMERR_DATATYPE, _("Data type %d not supported\n"),
381 /*@notreached@*/ break;
383 data = hfd(data, type);
385 hge(newH, RPMTAG_DIRINDEXES, NULL, (void **) &newDirIndexes, &count);
386 hge(newH, RPMTAG_DIRNAMES, NULL, (void **) &newDirNames, NULL);
387 hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
388 hge(h, RPMTAG_DIRNAMES, NULL, (void **) &data, &dirNamesCount);
390 dirNames = xcalloc(dirNamesCount + fc, sizeof(char *));
391 for (i = 0; i < dirNamesCount; i++)
392 dirNames[i] = ((char **) data)[i];
393 dirCount = dirNamesCount;
394 newdata = xmalloc(fc * sizeof(int_32));
395 for (i = 0, k = 0; i < count; i++) {
396 if (actions[i] == FA_SKIPMULTILIB)
398 for (j = 0; j < dirCount; j++)
399 if (!strcmp(dirNames[j], newDirNames[newDirIndexes[i]]))
402 dirNames[dirCount++] = newDirNames[newDirIndexes[i]];
403 ((int_32 *) newdata)[k++] = j;
405 headerAddOrAppendEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, newdata, fc);
406 if (dirCount > dirNamesCount)
407 headerAddOrAppendEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
408 dirNames + dirNamesCount,
409 dirCount - dirNamesCount);
410 data = hfd(data, -1);
411 newDirNames = hfd(newDirNames, -1);
415 for (i = 0; i < 9; i += 3) {
416 const char **Names, **EVR, **newNames, **newEVR;
418 uint_32 *Flags, *newFlags;
419 int Count = 0, newCount = 0;
421 if (!hge(newH, requireTags[i], &nnt, (void **) &newNames, &newCount))
424 hge(newH, requireTags[i+1], &nvt, (void **) &newEVR, NULL);
425 hge(newH, requireTags[i+2], NULL, (void **) &newFlags, NULL);
426 if (hge(h, requireTags[i], &rnt, (void **) &Names, &Count))
428 hge(h, requireTags[i+1], NULL, (void **) &EVR, NULL);
429 hge(h, requireTags[i+2], NULL, (void **) &Flags, NULL);
430 for (j = 0; j < newCount; j++)
431 for (k = 0; k < Count; k++)
432 if (!strcmp (newNames[j], Names[k])
433 && !strcmp (newEVR[j], EVR[k])
434 && (newFlags[j] & RPMSENSE_SENSEMASK) ==
435 (Flags[k] & RPMSENSE_SENSEMASK))
441 for (j = 0, k = 0; j < newCount; j++) {
442 if (!newNames[j] || !isDependsMULTILIB(newFlags[j]))
445 newNames[k] = newNames[j];
446 newEVR[k] = newEVR[j];
447 newFlags[k] = newFlags[j];
452 headerAddOrAppendEntry(h, requireTags[i],
453 RPM_STRING_ARRAY_TYPE, newNames, k);
454 headerAddOrAppendEntry(h, requireTags[i+1],
455 RPM_STRING_ARRAY_TYPE, newEVR, k);
456 headerAddOrAppendEntry(h, requireTags[i+2], RPM_INT32_TYPE,
459 newNames = hfd(newNames, nnt);
460 newEVR = hfd(newEVR, nvt);
461 Names = hfd(Names, rnt);
467 * Mark files in database shared with this package as "replaced".
468 * @param psm package state machine data
471 static int markReplacedFiles(PSM_t psm)
473 const rpmTransactionSet ts = psm->ts;
475 HGE_t hge = (HGE_t)fi->hge;
476 const struct sharedFileInfo * replaced = fi->replaced;
477 const struct sharedFileInfo * sfi;
478 rpmdbMatchIterator mi;
480 unsigned int * offsets;
484 if (!(fi->fc > 0 && fi->replaced))
488 for (sfi = replaced; sfi->otherPkg; sfi++) {
489 if (prev && prev == sfi->otherPkg)
491 prev = sfi->otherPkg;
497 offsets = alloca(num * sizeof(*offsets));
499 for (sfi = replaced; sfi->otherPkg; sfi++) {
500 if (prev && prev == sfi->otherPkg)
502 prev = sfi->otherPkg;
503 offsets[num++] = sfi->otherPkg;
506 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
507 rpmdbAppendIterator(mi, offsets, num);
510 while ((h = rpmdbNextIterator(mi)) != NULL) {
517 if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
520 prev = rpmdbGetIteratorOffset(mi);
522 while (sfi->otherPkg && sfi->otherPkg == prev) {
523 assert(sfi->otherFileNum < count);
524 if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
525 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
527 /* Modified header will be rewritten. */
529 rpmdbSetIteratorModified(mi, modified);
536 rpmdbFreeIterator(mi);
543 static rpmRC chkdir (const char * dpath, const char * dname)
548 if ((rc = Stat(dpath, &st)) < 0) {
549 int ut = urlPath(dpath, NULL);
558 /* XXX this will only create last component of directory path */
559 rc = Mkdir(dpath, 0755);
565 rpmError(RPMERR_CREATE, _("cannot create %s %s\n"),
570 if ((rc = Access(dpath, W_OK))) {
571 rpmError(RPMERR_CREATE, _("cannot write to %s\n"), dpath);
577 rpmRC rpmInstallSourcePackage(const char * rootDir, FD_t fd,
578 const char ** specFilePtr,
579 rpmCallbackFunction notify, rpmCallbackData notifyData,
583 rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
584 TFI_t fi = xcalloc(sizeof(*fi), 1);
585 const char * _sourcedir = NULL;
586 const char * _specdir = NULL;
587 const char * specFile = NULL;
598 ts->notifyData = notifyData;
600 rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
605 rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
610 (void) rpmtransAddPackage(ts, h, fd, NULL, 0, NULL);
613 fi->ap = ts->addedPackages.list;
617 headerFree(h); /* XXX reference held by transaction set */
620 rpmInstallLoadMacros(fi, fi->h);
622 memset(psm, 0, sizeof(*psm));
628 if (hge(h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
629 *cookie = xstrdup(*cookie);
632 /* XXX FIXME: can't do endian neutral MD5 verification yet. */
633 fi->fmd5s = hfd(fi->fmd5s, -1);
635 /* XXX FIXME: don't do per-file mapping, force global flags. */
636 fi->fmapflags = hfd(fi->fmapflags, -1);
637 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
644 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
645 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
646 for (i = 0; i < fi->fc; i++) {
647 fi->fuids[i] = fi->uid;
648 fi->fgids[i] = fi->gid;
651 for (i = 0; i < fi->fc; i++) {
652 fi->actions[i] = FA_CREATE;
655 rpmBuildFileList(fi->h, &fi->apath, NULL);
658 if (headerIsEntry(fi->h, RPMTAG_COOKIE))
659 for (i = 0; i < fi->fc; i++)
660 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
663 /* Find the spec file by name. */
664 for (i = 0; i < fi->fc; i++) {
665 const char * t = fi->apath[i];
666 t += strlen(fi->apath[i]) - 5;
667 if (!strcmp(t, ".spec")) break;
671 _sourcedir = rpmGenPath(ts->rootDir, "%{_sourcedir}", "");
672 rc = chkdir(_sourcedir, "sourcedir");
678 _specdir = rpmGenPath(ts->rootDir, "%{_specdir}", "");
679 rc = chkdir(_specdir, "specdir");
685 /* Build dnl/dil with {_sourcedir, _specdir} as values. */
687 int speclen = strlen(_specdir) + 2;
688 int sourcelen = strlen(_sourcedir) + 2;
691 fi->dnl = hfd(fi->dnl, -1);
694 fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl) + fi->fc * sizeof(*fi->dil) +
695 speclen + sourcelen);
696 fi->dil = (int *)(fi->dnl + fi->dc);
697 memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
699 fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
700 fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
701 (void) stpcpy( stpcpy(t, _specdir), "/");
703 t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
704 (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
707 rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
712 psm->goal = PSM_PKGINSTALL;
714 rc = psmStage(psm, PSM_PROCESS);
716 (void) psmStage(psm, PSM_FINI);
718 if (rc) rc = RPMRC_FAIL;
721 if (rc == RPMRC_OK && specFile && specFilePtr)
722 *specFilePtr = specFile;
724 specFile = _free(specFile);
726 _specdir = _free(_specdir);
727 _sourcedir = _free(_sourcedir);
742 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
745 * Return scriptlet name from tag.
746 * @param tag scriptlet tag
747 * @return name of scriptlet
749 static /*@observer@*/ const char * const tag2sln(int tag)
752 case RPMTAG_PREIN: return "%pre";
753 case RPMTAG_POSTIN: return "%post";
754 case RPMTAG_PREUN: return "%preun";
755 case RPMTAG_POSTUN: return "%postun";
756 case RPMTAG_VERIFYSCRIPT: return "%verify";
758 return "%unknownscript";
762 * Run scriptlet with args.
764 * Run a script with an interpreter. If the interpreter is not specified,
765 * /bin/sh will be used. If the interpreter is /bin/sh, then the args from
766 * the header will be ignored, passing instead arg1 and arg2.
768 * @param psm package state machine data
770 * @param sln name of scriptlet section
771 * @param progArgc no. of args from header
772 * @param progArgv args from header, progArgv[0] is the interpreter to use
773 * @param script scriptlet from header
774 * @param arg1 no. instances of package installed after scriptlet exec
776 * @param arg2 ditto, but for the target package
777 * @return 0 on success, 1 on error
779 static int runScript(PSM_t psm, Header h,
781 int progArgc, const char ** progArgv,
782 const char * script, int arg1, int arg2)
784 const rpmTransactionSet ts = psm->ts;
788 const char ** argv = NULL;
790 const char ** prefixes = NULL;
793 const char * oldPrefix;
796 char * prefixBuf = NULL;
799 const char * fn = NULL;
801 int freePrefixes = 0;
804 const char *n, *v, *r;
806 if (!progArgv && !script)
810 argv = alloca(5 * sizeof(char *));
814 argv = alloca((progArgc + 4) * sizeof(char *));
815 memcpy(argv, progArgv, progArgc * sizeof(char *));
819 headerNVR(h, &n, &v, &r);
820 if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
822 } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
823 prefixes = &oldPrefix;
830 for (i = 0; i < numPrefixes; i++) {
831 len = strlen(prefixes[i]);
832 if (len > maxPrefixLength) maxPrefixLength = len;
834 prefixBuf = alloca(maxPrefixLength + 50);
838 if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) {
839 if (freePrefixes) free(prefixes);
844 (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
845 (void)Fwrite("set -x\n", sizeof(char), 7, fd);
847 (void)Fwrite(script, sizeof(script[0]), strlen(script), fd);
850 { const char * sn = fn;
851 if (!ts->chrootDone &&
852 !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0'))
854 sn += strlen(ts->rootDir)-1;
860 char *av = alloca(20);
861 sprintf(av, "%d", arg1);
865 char *av = alloca(20);
866 sprintf(av, "%d", arg2);
873 if (ts->scriptFd != NULL) {
874 if (rpmIsVerbose()) {
875 out = fdDup(Fileno(ts->scriptFd));
877 out = Fopen("/dev/null", "w.fdio");
879 out = fdDup(Fileno(ts->scriptFd));
883 out = fdDup(STDOUT_FILENO);
884 out = fdLink(out, "runScript persist");
887 if (!(child = fork())) {
888 const char * rootDir;
891 pipes[0] = pipes[1] = 0;
892 /* make stdin inaccessible */
895 dup2(pipes[0], STDIN_FILENO);
898 if (ts->scriptFd != NULL) {
899 if (Fileno(ts->scriptFd) != STDERR_FILENO)
900 dup2(Fileno(ts->scriptFd), STDERR_FILENO);
901 if (Fileno(out) != STDOUT_FILENO)
902 dup2(Fileno(out), STDOUT_FILENO);
903 /* make sure we don't close stdin/stderr/stdout by mistake! */
904 if (Fileno(out) > STDERR_FILENO && Fileno(out) != Fileno(ts->scriptFd)) {
907 if (Fileno(ts->scriptFd) > STDERR_FILENO) {
908 Fclose (ts->scriptFd);
912 { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
913 const char *path = SCRIPT_PATH;
915 if (ipath && ipath[5] != '%')
918 if (ipath) free((void *)ipath);
921 for (i = 0; i < numPrefixes; i++) {
922 sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
925 /* backwards compatibility */
927 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
932 rootDir = ts->rootDir;
933 switch(urlIsURL(rootDir)) {
935 rootDir += sizeof("file://") - 1;
936 rootDir = strchr(rootDir, '/');
939 if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) {
940 /*@-unrecog@*/ chroot(rootDir); /*@=unrecog@*/
943 execv(argv[0], (char *const *)argv);
953 if (waitpid(child, &status, 0) < 0) {
954 rpmError(RPMERR_SCRIPT,
955 _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"),
956 sln, n, v, r, strerror (errno));
957 /* XXX what to do here? */
960 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
961 rpmError(RPMERR_SCRIPT,
962 _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"),
963 sln, n, v, r, WEXITSTATUS(status));
968 if (freePrefixes) prefixes = hfd(prefixes, ipt);
970 Fclose(out); /* XXX dup'd STDOUT_FILENO */
973 if (!rpmIsDebug()) unlink(fn);
981 * Retrieve and run scriptlet from header.
982 * @param psm package state machine data
983 * @return rpmRC return code
985 static rpmRC runInstScript(PSM_t psm)
998 * headerGetEntry() sets the data pointer to NULL if the entry does
1001 hge(fi->h, psm->progTag, &ptt, (void **) &programArgv, &programArgc);
1002 hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
1004 if (programArgv && ptt == RPM_STRING_TYPE) {
1005 argv = alloca(sizeof(char *));
1006 *argv = (const char *) programArgv;
1008 argv = (const char **) programArgv;
1011 rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), programArgc, argv,
1012 script, psm->scriptArg, -1);
1014 programArgv = hfd(programArgv, ptt);
1015 script = hfd(script, stt);
1020 * @param psm package state machine data
1024 * @param triggersAlreadyRun
1027 static int handleOneTrigger(PSM_t psm, Header sourceH, Header triggeredH,
1028 int arg2, char * triggersAlreadyRun)
1030 const rpmTransactionSet ts = psm->ts;
1032 HGE_t hge = fi->hge;
1033 HFD_t hfd = fi->hfd;
1034 const char ** triggerNames;
1035 const char ** triggerEVR;
1036 const char ** triggerScripts;
1037 const char ** triggerProgs;
1038 int_32 * triggerFlags;
1039 int_32 * triggerIndices;
1040 int_32 tnt, tvt, tft;
1041 const char * triggerPackageName;
1042 const char * sourceName;
1044 rpmRC rc = RPMRC_OK;
1048 if (!hge(triggeredH, RPMTAG_TRIGGERNAME, &tnt,
1049 (void **) &triggerNames, &numTriggers))
1052 headerNVR(sourceH, &sourceName, NULL, NULL);
1054 hge(triggeredH, RPMTAG_TRIGGERFLAGS, &tft, (void **) &triggerFlags, NULL);
1055 hge(triggeredH, RPMTAG_TRIGGERVERSION, &tvt, (void **) &triggerEVR, NULL);
1057 for (i = 0; i < numTriggers; i++) {
1058 int_32 tit, tst, tpt;
1060 if (!(triggerFlags[i] & psm->sense)) continue;
1061 if (strcmp(triggerNames[i], sourceName)) continue;
1064 * For some reason, the TRIGGERVERSION stuff includes the name of
1065 * the package which the trigger is based on. We need to skip
1066 * over that here. I suspect that we'll change our minds on this
1067 * and remove that, so I'm going to just 'do the right thing'.
1069 skip = strlen(triggerNames[i]);
1070 if (!strncmp(triggerEVR[i], triggerNames[i], skip) &&
1071 (triggerEVR[i][skip] == '-'))
1076 if (!headerMatchesDepFlags(sourceH, triggerNames[i],
1077 triggerEVR[i] + skip, triggerFlags[i]))
1080 hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
1081 (void **) &triggerIndices, NULL);
1082 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
1083 (void **) &triggerScripts, NULL);
1084 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
1085 (void **) &triggerProgs, NULL);
1087 headerNVR(triggeredH, &triggerPackageName, NULL, NULL);
1092 arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName);
1094 /* XXX W2DO? same as "execution of script failed" */
1097 arg1 += psm->countCorrection;
1098 index = triggerIndices[i];
1099 if (!triggersAlreadyRun || !triggersAlreadyRun[index]) {
1100 rc = runScript(psm, triggeredH, "%trigger", 1,
1101 triggerProgs + index, triggerScripts[index],
1103 if (triggersAlreadyRun) triggersAlreadyRun[index] = 1;
1108 triggerIndices = hfd(triggerIndices, tit);
1109 triggerScripts = hfd(triggerScripts, tst);
1110 triggerProgs = hfd(triggerProgs, tpt);
1113 * Each target/source header pair can only result in a single
1119 triggerNames = hfd(triggerNames, tnt);
1120 triggerFlags = hfd(triggerFlags, tft);
1121 triggerEVR = hfd(triggerEVR, tvt);
1127 * Run trigger scripts in the database that are fired by this header.
1128 * @param psm package state machine data
1129 * @return 0 on success, 1 on error
1131 static int runTriggers(PSM_t psm)
1133 const rpmTransactionSet ts = psm->ts;
1136 rpmRC rc = RPMRC_OK;
1138 numPackage = rpmdbCountPackages(ts->rpmdb, fi->name) + psm->countCorrection;
1142 { Header triggeredH;
1143 rpmdbMatchIterator mi;
1144 int countCorrection = psm->countCorrection;
1146 psm->countCorrection = 0;
1147 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, fi->name, 0);
1148 while((triggeredH = rpmdbNextIterator(mi)) != NULL) {
1149 rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
1152 rpmdbFreeIterator(mi);
1153 psm->countCorrection = countCorrection;
1160 * Run triggers from this header that are fired by headers in the database.
1161 * @param psm package state machine data
1162 * @return 0 on success, 1 on error
1164 static int runImmedTriggers(PSM_t psm)
1166 const rpmTransactionSet ts = psm->ts;
1168 HGE_t hge = fi->hge;
1169 HFD_t hfd = fi->hfd;
1170 const char ** triggerNames;
1172 int_32 * triggerIndices;
1174 int numTriggerIndices;
1176 rpmRC rc = RPMRC_OK;
1178 if (!hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
1179 (void **) &triggerNames, &numTriggers))
1182 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit, (void **) &triggerIndices,
1183 &numTriggerIndices);
1184 triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
1185 memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
1187 { Header sourceH = NULL;
1190 for (i = 0; i < numTriggers; i++) {
1191 rpmdbMatchIterator mi;
1193 if (triggersRun[triggerIndices[i]]) continue;
1195 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, triggerNames[i], 0);
1197 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
1198 rc |= handleOneTrigger(psm, sourceH, fi->h,
1199 rpmdbGetIteratorCount(mi),
1203 rpmdbFreeIterator(mi);
1206 triggerIndices = hfd(triggerIndices, tit);
1207 triggerNames = hfd(triggerNames, tnt);
1211 /*@observer@*/ static const char *const pkgStageString(pkgStage a) {
1213 case PSM_UNKNOWN: return "unknown";
1215 case PSM_PKGINSTALL: return " install";
1216 case PSM_PKGERASE: return " erase";
1217 case PSM_PKGCOMMIT: return " commit";
1218 case PSM_PKGSAVE: return "repackage";
1220 case PSM_INIT: return "init";
1221 case PSM_PRE: return "pre";
1222 case PSM_PROCESS: return "process";
1223 case PSM_POST: return "post";
1224 case PSM_UNDO: return "undo";
1225 case PSM_FINI: return "fini";
1227 case PSM_CREATE: return "create";
1228 case PSM_NOTIFY: return "notify";
1229 case PSM_DESTROY: return "destroy";
1230 case PSM_COMMIT: return "commit";
1232 case PSM_CHROOT_IN: return "chrootin";
1233 case PSM_CHROOT_OUT: return "chrootout";
1234 case PSM_SCRIPT: return "script";
1235 case PSM_TRIGGERS: return "triggers";
1236 case PSM_IMMED_TRIGGERS: return "immedtriggers";
1238 case PSM_RPMIO_FLAGS: return "rpmioflags";
1240 case PSM_RPMDB_LOAD: return "rpmdbload";
1241 case PSM_RPMDB_ADD: return "rpmdbadd";
1242 case PSM_RPMDB_REMOVE: return "rpmdbremove";
1244 default: return "???";
1250 * @todo Packages w/o files never get a callback, hence don't get displayed
1251 * on install with -v.
1253 int psmStage(PSM_t psm, pkgStage stage)
1255 const rpmTransactionSet ts = psm->ts;
1257 HGE_t hge = fi->hge;
1258 HFD_t hfd = fi->hfd;
1266 rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"),
1267 psm->stepName, fi->name, fi->version, fi->release,
1268 fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST));
1271 * When we run scripts, we pass an argument which is the number of
1272 * versions of this package that will be installed when we are
1275 psm->npkgs_installed = rpmdbCountPackages(ts->rpmdb, fi->name);
1276 if (psm->npkgs_installed < 0) {
1281 if (psm->goal == PSM_PKGINSTALL) {
1282 psm->scriptArg = psm->npkgs_installed + 1;
1284 assert(psm->mi == NULL);
1285 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, fi->name, 0);
1286 rpmdbSetIteratorVersion(psm->mi, fi->version);
1287 rpmdbSetIteratorRelease(psm->mi, fi->release);
1288 while ((psm->oh = rpmdbNextIterator(psm->mi))) {
1289 fi->record = rpmdbGetIteratorOffset(psm->mi);
1290 psm->oh = (ts->transFlags & RPMTRANS_FLAG_MULTILIB)
1291 ? headerCopy(psm->oh) : NULL;
1294 rpmdbFreeIterator(psm->mi);
1298 if (fi->fc > 0 && fi->fstates == NULL) {
1299 fi->fstates = xmalloc(sizeof(*fi->fstates) * fi->fc);
1300 memset(fi->fstates, RPMFILE_STATE_NORMAL, fi->fc);
1303 if (fi->fc <= 0) break;
1304 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1307 * Old format relocateable packages need the entire default
1308 * prefix stripped to form the cpio list, while all other packages
1309 * need the leading / stripped.
1312 rc = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
1313 fi->striplen = (rc ? strlen(p) + 1 : 1);
1316 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
1318 if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
1319 buildOrigFileList(fi->h, &fi->apath, NULL);
1321 rpmBuildFileList(fi->h, &fi->apath, NULL);
1323 if (fi->fuser == NULL)
1324 hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
1325 (void **) &fi->fuser, NULL);
1326 if (fi->fgroup == NULL)
1327 hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
1328 (void **) &fi->fgroup, NULL);
1329 if (fi->fuids == NULL)
1330 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
1331 if (fi->fgids == NULL)
1332 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
1335 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1336 psm->scriptArg = psm->npkgs_installed - 1;
1338 /* Retrieve installed header. */
1339 rc = psmStage(psm, PSM_RPMDB_LOAD);
1341 if (psm->goal == PSM_PKGSAVE) {
1342 /* Open output package for writing. */
1343 { const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
1344 const char * pkgbn =
1345 headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
1348 psm->pkgURL = rpmGenPath("%{?_repackage_root:%{_repackage_root}}",
1349 "%{?_repackage_dir:%{_repackage_dir}}",
1351 pkgbn = _free(pkgbn);
1352 (void) urlPath(psm->pkgURL, &psm->pkgfn);
1353 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
1354 if (psm->fd == NULL || Ferror(psm->fd)) {
1362 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1364 /* Change root directory if requested and not already done. */
1365 rc = psmStage(psm, PSM_CHROOT_IN);
1367 if (psm->goal == PSM_PKGINSTALL) {
1368 psm->scriptTag = RPMTAG_PREIN;
1369 psm->progTag = RPMTAG_PREINPROG;
1371 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
1372 /* XXX FIXME: implement %triggerprein. */
1375 if (!(ts->transFlags & RPMTRANS_FLAG_NOPRE)) {
1376 rc = psmStage(psm, PSM_SCRIPT);
1378 rpmError(RPMERR_SCRIPT,
1379 _("%s: %s scriptlet failed (%d), skipping %s-%s-%s\n"),
1380 psm->stepName, tag2sln(psm->scriptTag), rc,
1381 fi->name, fi->version, fi->release);
1387 if (psm->goal == PSM_PKGERASE) {
1388 psm->scriptTag = RPMTAG_PREUN;
1389 psm->progTag = RPMTAG_PREUNPROG;
1390 psm->sense = RPMSENSE_TRIGGERUN;
1391 psm->countCorrection = -1;
1393 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERUN)) {
1394 /* Run triggers in other package(s) this package sets off. */
1395 rc = psmStage(psm, PSM_TRIGGERS);
1398 /* Run triggers in this package other package(s) set off. */
1399 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
1403 if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
1404 rc = psmStage(psm, PSM_SCRIPT);
1406 if (psm->goal == PSM_PKGSAVE) {
1407 /* Regenerate original header. */
1411 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
1412 psm->oh = headerCopyLoad(uh);
1415 psm->oh = headerLink(fi->h);
1419 /* Retrieve type of payload compression. */
1420 rc = psmStage(psm, PSM_RPMIO_FLAGS);
1422 /* Write the lead section into the package. */
1425 struct rpmlead lead;
1428 rpmGetArchInfo(NULL, &archnum);
1429 rpmGetOsInfo(NULL, &osnum);
1432 memset(&lead, 0, sizeof(lead));
1433 /* XXX Set package version conditioned on noDirTokens. */
1436 lead.type = RPMLEAD_BINARY;
1437 lead.archnum = archnum;
1439 lead.signature_type = RPMSIGTYPE_HEADERSIG;
1442 sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
1443 strncpy(lead.name, buf, sizeof(lead.name));
1446 rc = writeLead(psm->fd, &lead);
1448 rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
1449 Fstrerror(psm->fd));
1455 /* Write the signature section into the package. */
1456 { Header sig = headerRegenSigHeader(fi->h);
1457 rc = rpmWriteSignature(psm->fd, sig);
1462 /* Write the metadata section into the package. */
1463 rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
1468 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1470 if (psm->goal == PSM_PKGINSTALL) {
1471 struct availablePackage * alp = fi->ap;
1474 if (fi->fc <= 0) break;
1475 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1477 for (i = 0; i < fi->fc; i++) {
1483 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
1484 rpmMessage(RPMMESS_WARNING,
1485 _("user %s does not exist - using root\n"),
1488 /* XXX this diddles header memory. */
1489 fi->fmodes[i] &= ~S_ISUID; /* turn off the suid bit */
1492 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
1493 rpmMessage(RPMMESS_WARNING,
1494 _("group %s does not exist - using root\n"),
1497 /* XXX this diddles header memory. */
1498 fi->fmodes[i] &= ~S_ISGID; /* turn off the sgid bit */
1500 if (fi->fuids) fi->fuids[i] = uid;
1501 if (fi->fgids) fi->fgids[i] = gid;
1504 /* Retrieve type of payload compression. */
1505 rc = psmStage(psm, PSM_RPMIO_FLAGS);
1507 psm->cfd = Fdopen(fdDup(Fileno(alp->fd)), psm->rpmio_flags);
1509 rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
1510 psm->cfd, NULL, &psm->failedFile);
1511 (void) fsmTeardown(fi->fsm);
1513 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1516 errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1519 rc = psmStage(psm, PSM_COMMIT);
1522 rpmError(RPMERR_CPIO,
1523 _("unpacking of archive failed%s%s: %s\n"),
1524 (psm->failedFile != NULL ? _(" on file ") : ""),
1525 (psm->failedFile != NULL ? psm->failedFile : ""),
1530 psm->what = RPMCALLBACK_INST_PROGRESS;
1531 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1532 psm->total = psm->amount;
1533 (void) psmStage(psm, PSM_NOTIFY);
1535 if (psm->goal == PSM_PKGERASE) {
1537 if (fi->fc <= 0) break;
1538 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1539 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
1541 psm->what = RPMCALLBACK_UNINST_START;
1542 psm->amount = fi->fc; /* XXX W2DO? looks wrong. */
1543 psm->total = fi->fc;
1544 (void) psmStage(psm, PSM_NOTIFY);
1546 rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
1547 NULL, NULL, &psm->failedFile);
1548 (void) fsmTeardown(fi->fsm);
1550 psm->what = RPMCALLBACK_UNINST_STOP;
1551 psm->amount = 0; /* XXX W2DO? looks wrong. */
1552 psm->total = fi->fc;
1553 (void) psmStage(psm, PSM_NOTIFY);
1556 if (psm->goal == PSM_PKGSAVE) {
1557 fileAction * actions = fi->actions;
1558 fileAction action = fi->action;
1560 fi->action = FA_COPYOUT;
1564 psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
1566 /* XXX failedFile? */
1567 rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd, NULL, NULL);
1568 (void) fsmTeardown(fi->fsm);
1570 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1575 fi->action = action;
1576 fi->actions = actions;
1580 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1582 if (psm->goal == PSM_PKGINSTALL) {
1583 int_32 installTime = time(NULL);
1585 if (fi->fc > 0 && fi->fstates)
1586 headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
1587 fi->fstates, fi->fc);
1589 headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
1592 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB) {
1593 uint_32 multiLib, * newMultiLib, * p;
1595 if (hge(fi->h, RPMTAG_MULTILIBS, NULL, (void **) &newMultiLib, NULL) &&
1596 hge(psm->oh, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL)) {
1598 multiLib |= *newMultiLib;
1599 headerModifyEntry(psm->oh, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
1602 rc = mergeFiles(fi, psm->oh, fi->h);
1608 * If this package has already been installed, remove it from
1609 * the database before adding the new one.
1611 if (fi->record && !(ts->transFlags & RPMTRANS_FLAG_APPLYONLY)) {
1612 rc = psmStage(psm, PSM_RPMDB_REMOVE);
1616 rc = psmStage(psm, PSM_RPMDB_ADD);
1619 psm->scriptTag = RPMTAG_POSTIN;
1620 psm->progTag = RPMTAG_POSTINPROG;
1621 psm->sense = RPMSENSE_TRIGGERIN;
1622 psm->countCorrection = 0;
1624 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOST)) {
1625 rc = psmStage(psm, PSM_SCRIPT);
1628 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERIN)) {
1629 /* Run triggers in other package(s) this package sets off. */
1630 rc = psmStage(psm, PSM_TRIGGERS);
1633 /* Run triggers in this package other package(s) set off. */
1634 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
1638 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
1639 rc = markReplacedFiles(psm);
1642 if (psm->goal == PSM_PKGERASE) {
1644 psm->scriptTag = RPMTAG_POSTUN;
1645 psm->progTag = RPMTAG_POSTUNPROG;
1646 psm->sense = RPMSENSE_TRIGGERPOSTUN;
1647 psm->countCorrection = -1;
1649 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOSTUN)) {
1650 rc = psmStage(psm, PSM_SCRIPT);
1651 /* XXX WTFO? postun failures don't cause erasure failure. */
1654 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
1655 /* Run triggers in other package(s) this package sets off. */
1656 rc = psmStage(psm, PSM_TRIGGERS);
1660 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
1661 rc = psmStage(psm, PSM_RPMDB_REMOVE);
1663 if (psm->goal == PSM_PKGSAVE) {
1666 /* Restore root directory if changed. */
1667 (void) psmStage(psm, PSM_CHROOT_OUT);
1672 /* Restore root directory if changed. */
1673 (void) psmStage(psm, PSM_CHROOT_OUT);
1676 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1682 if (psm->goal == PSM_PKGSAVE) {
1684 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"), psm->pkgURL);
1687 if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE)) {
1692 headerFree(psm->oh);
1695 psm->pkgURL = _free(psm->pkgURL);
1696 psm->rpmio_flags = _free(psm->rpmio_flags);
1697 psm->failedFile = _free(psm->failedFile);
1699 fi->fgids = _free(fi->fgids);
1700 fi->fuids = _free(fi->fuids);
1701 fi->fgroup = hfd(fi->fgroup, -1);
1702 fi->fuser = hfd(fi->fuser, -1);
1703 fi->apath = _free(fi->apath);
1704 fi->fstates = _free(fi->fstates);
1708 case PSM_PKGINSTALL:
1713 psm->stepName = pkgStageString(stage);
1715 rc = psmStage(psm, PSM_INIT);
1716 if (!rc) rc = psmStage(psm, PSM_PRE);
1717 if (!rc) rc = psmStage(psm, PSM_PROCESS);
1718 if (!rc) rc = psmStage(psm, PSM_POST);
1719 (void) psmStage(psm, PSM_FINI);
1727 if (ts && ts->notify)
1728 (void) ts->notify(fi->h, psm->what, psm->amount, psm->total,
1729 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
1734 if (!(ts->transFlags & RPMTRANS_FLAG_PKGCOMMIT)) break;
1735 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
1737 rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
1738 NULL, NULL, &psm->failedFile);
1739 (void) fsmTeardown(fi->fsm);
1743 /* Change root directory if requested and not already done. */
1744 if (ts->rootDir && !ts->chrootDone && !psm->chrootDone) {
1745 static int _loaded = 0;
1748 * This loads all of the name services libraries, in case we
1749 * don't have access to them in the chroot().
1752 (void)getpwnam("root");
1759 rc = chroot(ts->rootDir);
1761 psm->chrootDone = ts->chrootDone = 1;
1764 case PSM_CHROOT_OUT:
1765 /* Restore root directory if changed. */
1766 if (psm->chrootDone) {
1770 psm->chrootDone = ts->chrootDone = 0;
1775 rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"),
1776 psm->stepName, tag2sln(psm->scriptTag));
1777 rc = runInstScript(psm);
1780 /* Run triggers in other package(s) this package sets off. */
1781 rc = runTriggers(psm);
1783 case PSM_IMMED_TRIGGERS:
1784 /* Run triggers in this package other package(s) set off. */
1785 rc = runImmedTriggers(psm);
1788 case PSM_RPMIO_FLAGS:
1789 { const char * payload_compressor = NULL;
1792 if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
1793 (void **) &payload_compressor, NULL))
1794 payload_compressor = "gzip";
1795 psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
1797 t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
1798 if (!strcmp(payload_compressor, "gzip"))
1799 t = stpcpy(t, ".gzdio");
1800 if (!strcmp(payload_compressor, "bzip2"))
1801 t = stpcpy(t, ".bzdio");
1805 case PSM_RPMDB_LOAD:
1806 assert(psm->mi == NULL);
1807 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
1808 &fi->record, sizeof(fi->record));
1810 fi->h = rpmdbNextIterator(psm->mi);
1812 fi->h = headerLink(fi->h);
1813 rpmdbFreeIterator(psm->mi);
1815 rc = (fi->h ? RPMRC_OK : RPMRC_FAIL);
1818 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1819 rc = rpmdbAdd(ts->rpmdb, ts->id, fi->h);
1821 case PSM_RPMDB_REMOVE:
1822 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1823 rc = rpmdbRemove(ts->rpmdb, ts->id, fi->record);