1 /** \ingroup rpmtrans payload
3 * Package state machine to handle a package from a transaction set.
12 #include "rpmlead.h" /* writeLead proto */
13 #include "signature.h" /* signature constants */
15 #include "rpmdb.h" /* XXX for db_chrootDone */
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 */
25 /*@access rpmdb @*/ /* compared with NULL */
27 /*@-redecl -declundef -exportheadervar@*/
29 extern const char * chroot_prefix;
30 /*@=redecl =declundef =exportheadervar@*/
32 int rpmVersionCompare(Header first, Header second)
34 const char * one, * two;
35 int_32 * epochOne, * epochTwo;
38 if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
40 if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo,
44 if (epochOne && !epochTwo)
46 else if (!epochOne && epochTwo)
48 else if (epochOne && epochTwo) {
49 if (*epochOne < *epochTwo)
51 else if (*epochOne > *epochTwo)
55 rc = headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
56 rc = headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
58 rc = rpmvercmp(one, two);
62 rc = headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
63 rc = headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
65 return rpmvercmp(one, two);
68 void loadFi(Header h, TFI_t fi)
80 /* XXX avoid gcc noise on pointer (4th arg) cast(s) */
81 hge = (fi->type == TR_ADDED)
82 ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry;
84 fi->hae = (HAE_t) headerAddEntry;
85 fi->hme = (HME_t) headerModifyEntry;
86 fi->hre = (HRE_t) headerRemoveEntry;
87 fi->hfd = hfd = headerFreeData;
90 if (h && fi->h == NULL) fi->h = headerLink(h);
93 /* Duplicate name-version-release so that headers can be free'd. */
94 rc = hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL);
95 fi->name = xstrdup(fi->name);
96 rc = hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL);
97 fi->version = xstrdup(fi->version);
98 rc = hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL);
99 fi->release = xstrdup(fi->release);
101 /* -1 means not found */
102 rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL);
103 fi->epoch = (rc ? *uip : -1);
104 /* 0 means unknown */
105 rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL);
106 fi->archiveSize = (rc ? *uip : 0);
108 if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) {
114 rc = hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
115 rc = hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
116 rc = hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL);
117 rc = hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL);
118 rc = hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL);
119 rc = hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL);
121 fi->action = FA_UNKNOWN;
124 /* actions is initialized earlier for added packages */
125 if (fi->actions == NULL)
126 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
131 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
132 rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
133 rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
134 rc = hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL);
135 rc = hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL);
136 rc = hge(fi->h, RPMTAG_FILERDEVS, NULL, (void **) &fi->frdevs, NULL);
138 /* 0 makes for noops */
139 fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
144 CPIO_MAP_ABSOLUTE | CPIO_MAP_ADDDOT | CPIO_ALL_HARDLINKS |
145 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
146 rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
147 rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
148 fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)),
149 fi->fsizes, fi->fc * sizeof(*fi->fsizes));
150 fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)),
151 fi->fflags, fi->fc * sizeof(*fi->fflags));
152 fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)),
153 fi->fmodes, fi->fc * sizeof(*fi->fmodes));
154 /* XXX there's a tedious segfault here for some version(s) of rpm */
156 fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)),
157 fi->fstates, fi->fc * sizeof(*fi->fstates));
159 fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates));
160 fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)),
161 fi->dil, fi->fc * sizeof(*fi->dil));
162 fi->h = headerFree(fi->h);
167 for (i = 0; i < fi->dc; i++) {
168 if ((len = strlen(fi->dnl[i])) > fi->dnlmax)
173 for (i = 0; i < fi->fc; i++) {
174 if ((len = strlen(fi->bnl[i])) > fi->bnlmax)
181 /*@-nullstate@*/ /* FIX: fi->h is NULL for TR_REMOVED */
186 void freeFi(TFI_t fi)
188 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
190 fi->name = _free(fi->name);
191 fi->version = _free(fi->version);
192 fi->release = _free(fi->release);
193 fi->actions = _free(fi->actions);
194 fi->replacedSizes = _free(fi->replacedSizes);
195 fi->replaced = _free(fi->replaced);
197 fi->bnl = hfd(fi->bnl, -1);
198 fi->dnl = hfd(fi->dnl, -1);
199 fi->obnl = hfd(fi->obnl, -1);
200 fi->odnl = hfd(fi->odnl, -1);
201 fi->flinks = hfd(fi->flinks, -1);
202 fi->fmd5s = hfd(fi->fmd5s, -1);
203 fi->fuser = hfd(fi->fuser, -1);
204 fi->fgroup = hfd(fi->fgroup, -1);
205 fi->flangs = hfd(fi->flangs, -1);
207 fi->apath = _free(fi->apath);
208 fi->fuids = _free(fi->fuids);
209 fi->fgids = _free(fi->fgids);
210 fi->fmapflags = _free(fi->fmapflags);
212 fi->fsm = freeFSM(fi->fsm);
218 fi->fsizes = hfd(fi->fsizes, -1);
219 fi->fflags = hfd(fi->fflags, -1);
220 fi->fmodes = hfd(fi->fmodes, -1);
221 fi->fstates = hfd(fi->fstates, -1);
222 fi->dil = hfd(fi->dil, -1);
226 fi->h = headerFree(fi->h);
228 /*@-nullstate@*/ /* FIX: fi->{name,version,release,actions,...,h} NULL */
233 /*@observer@*/ const char *const fiTypeString(TFI_t fi)
236 case TR_ADDED: return " install";
237 case TR_REMOVED: return " erase";
238 default: return "???";
244 * Macros to be defined from per-header tag values.
245 * @todo Should other macros be added from header when installing a package?
247 /*@observer@*/ /*@unchecked@*/
248 static struct tagMacro {
249 /*@observer@*/ /*@null@*/ const char * macroname; /*!< Macro name to define. */
250 rpmTag tag; /*!< Header tag to use for value. */
252 { "name", RPMTAG_NAME },
253 { "version", RPMTAG_VERSION },
254 { "release", RPMTAG_RELEASE },
255 { "epoch", RPMTAG_EPOCH },
260 * Define per-header macros.
261 * @param fi transaction element file info
265 static int rpmInstallLoadMacros(TFI_t fi, Header h)
266 /*@globals rpmGlobalMacroContext, internalState @*/
267 /*@modifies rpmGlobalMacroContext, internalState @*/
269 HGE_t hge = (HGE_t) fi->hge;
270 struct tagMacro * tagm;
272 /*@unused@*/ void * ptr;
273 /*@unused@*/ const char ** argv;
280 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
281 if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
285 sprintf(numbuf, "%d", *body.i32p);
286 addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
287 /*@switchbreak@*/ break;
288 case RPM_STRING_TYPE:
289 addMacro(NULL, tagm->macroname, NULL, body.str, -1);
290 /*@switchbreak@*/ break;
296 case RPM_STRING_ARRAY_TYPE:
297 case RPM_I18NSTRING_TYPE:
299 /*@switchbreak@*/ break;
306 * Copy file data from h to newH.
307 * @param h header from
308 * @param newH header to
309 * @param actions array of file dispositions
310 * @return 0 on success, 1 on failure
312 static int mergeFiles(TFI_t fi, Header h, Header newH)
315 HGE_t hge = (HGE_t)fi->hge;
316 HME_t hme = (HME_t)fi->hme;
317 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
318 fileAction * actions = fi->actions;
322 int_32 dirNamesCount, dirCount;
323 void * data, * newdata;
324 int_32 * dirIndexes, * newDirIndexes;
325 uint_32 * fileSizes, fileSize;
326 const char ** dirNames;
327 const char ** newDirNames;
328 static rpmTag mergeTags[] = {
338 RPMTAG_FILEGROUPNAME,
339 RPMTAG_FILEVERIFYFLAGS,
346 static rpmTag requireTags[] = {
347 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
348 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
349 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS
352 xx = hge(h, RPMTAG_SIZE, NULL, (void **) &fileSizes, NULL);
353 fileSize = *fileSizes;
354 xx = hge(newH, RPMTAG_FILESIZES, NULL, (void **) &fileSizes, &count);
355 for (i = 0, fc = 0; i < count; i++)
356 if (actions[i] != FA_SKIPMULTILIB) {
358 fileSize += fileSizes[i];
360 xx = hme(h, RPMTAG_SIZE, RPM_INT32_TYPE, &fileSize, 1);
363 for (i = 0; mergeTags[i]; i++) {
364 if (!hge(newH, mergeTags[i], &type, (void **) &data, &count))
369 newdata = xcalloc(fc, sizeof(int_8));
370 for (j = 0, k = 0; j < count; j++)
371 if (actions[j] != FA_SKIPMULTILIB)
372 ((int_8 *) newdata)[k++] = ((int_8 *) data)[j];
373 xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
375 /*@switchbreak@*/ break;
377 newdata = xcalloc(fc, sizeof(int_16));
378 for (j = 0, k = 0; j < count; j++)
379 if (actions[j] != FA_SKIPMULTILIB)
380 ((int_16 *) newdata)[k++] = ((int_16 *) data)[j];
381 xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
383 /*@switchbreak@*/ break;
385 newdata = xcalloc(fc, sizeof(int_32));
386 for (j = 0, k = 0; j < count; j++)
387 if (actions[j] != FA_SKIPMULTILIB)
388 ((int_32 *) newdata)[k++] = ((int_32 *) data)[j];
389 xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
391 /*@switchbreak@*/ break;
392 case RPM_STRING_ARRAY_TYPE:
393 newdata = xcalloc(fc, sizeof(char *));
394 for (j = 0, k = 0; j < count; j++)
395 if (actions[j] != FA_SKIPMULTILIB)
396 ((char **) newdata)[k++] = ((char **) data)[j];
397 xx = headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
399 /*@switchbreak@*/ break;
401 rpmError(RPMERR_DATATYPE, _("Data type %d not supported\n"),
404 /*@notreached@*/ /*@switchbreak@*/ break;
406 data = hfd(data, type);
409 xx = hge(newH, RPMTAG_DIRINDEXES, NULL, (void **) &newDirIndexes, &count);
410 xx = hge(newH, RPMTAG_DIRNAMES, NULL, (void **) &newDirNames, NULL);
411 xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
412 xx = hge(h, RPMTAG_DIRNAMES, NULL, (void **) &data, &dirNamesCount);
414 dirNames = xcalloc(dirNamesCount + fc, sizeof(*dirNames));
415 for (i = 0; i < dirNamesCount; i++)
416 dirNames[i] = ((char **) data)[i];
417 dirCount = dirNamesCount;
418 newdata = xcalloc(fc, sizeof(*newDirIndexes));
419 for (i = 0, k = 0; i < count; i++) {
420 if (actions[i] == FA_SKIPMULTILIB)
422 for (j = 0; j < dirCount; j++)
423 if (!strcmp(dirNames[j], newDirNames[newDirIndexes[i]]))
424 /*@innerbreak@*/ break;
426 dirNames[dirCount++] = newDirNames[newDirIndexes[i]];
427 ((int_32 *) newdata)[k++] = j;
429 xx = headerAddOrAppendEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, newdata, fc);
430 if (dirCount > dirNamesCount)
431 xx = headerAddOrAppendEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
432 dirNames + dirNamesCount,
433 dirCount - dirNamesCount);
434 data = hfd(data, -1);
435 newDirNames = hfd(newDirNames, -1);
439 for (i = 0; i < 9; i += 3) {
440 const char **Names, **EVR, **newNames, **newEVR;
441 rpmTagType nnt, nvt, rnt;
442 uint_32 *Flags, *newFlags;
443 int Count = 0, newCount = 0;
445 if (!hge(newH, requireTags[i], &nnt, (void **) &newNames, &newCount))
448 xx = hge(newH, requireTags[i+1], &nvt, (void **) &newEVR, NULL);
449 xx = hge(newH, requireTags[i+2], NULL, (void **) &newFlags, NULL);
450 if (hge(h, requireTags[i], &rnt, (void **) &Names, &Count))
452 xx = hge(h, requireTags[i+1], NULL, (void **) &EVR, NULL);
453 xx = hge(h, requireTags[i+2], NULL, (void **) &Flags, NULL);
454 for (j = 0; j < newCount; j++)
455 for (k = 0; k < Count; k++)
456 if (!strcmp (newNames[j], Names[k])
457 && !strcmp (newEVR[j], EVR[k])
458 && (newFlags[j] & RPMSENSE_SENSEMASK) ==
459 (Flags[k] & RPMSENSE_SENSEMASK))
462 /*@innerbreak@*/ break;
465 for (j = 0, k = 0; j < newCount; j++) {
466 if (!newNames[j] || !isDependsMULTILIB(newFlags[j]))
467 /*@innercontinue@*/ continue;
469 newNames[k] = newNames[j];
470 newEVR[k] = newEVR[j];
471 newFlags[k] = newFlags[j];
476 xx = headerAddOrAppendEntry(h, requireTags[i],
477 RPM_STRING_ARRAY_TYPE, newNames, k);
478 xx = headerAddOrAppendEntry(h, requireTags[i+1],
479 RPM_STRING_ARRAY_TYPE, newEVR, k);
480 xx = headerAddOrAppendEntry(h, requireTags[i+2], RPM_INT32_TYPE,
483 newNames = hfd(newNames, nnt);
484 newEVR = hfd(newEVR, nvt);
485 Names = hfd(Names, rnt);
491 * Mark files in database shared with this package as "replaced".
492 * @param psm package state machine data
495 static int markReplacedFiles(PSM_t psm)
496 /*@globals fileSystem@*/
497 /*@modifies psm, fileSystem @*/
499 const rpmTransactionSet ts = psm->ts;
501 HGE_t hge = (HGE_t)fi->hge;
502 const struct sharedFileInfo * replaced = fi->replaced;
503 const struct sharedFileInfo * sfi;
504 rpmdbMatchIterator mi;
506 unsigned int * offsets;
510 if (!(fi->fc > 0 && fi->replaced))
514 for (sfi = replaced; sfi->otherPkg; sfi++) {
515 if (prev && prev == sfi->otherPkg)
517 prev = sfi->otherPkg;
523 offsets = alloca(num * sizeof(*offsets));
525 for (sfi = replaced; sfi->otherPkg; sfi++) {
526 if (prev && prev == sfi->otherPkg)
528 prev = sfi->otherPkg;
529 offsets[num++] = sfi->otherPkg;
532 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
533 xx = rpmdbAppendIterator(mi, offsets, num);
534 xx = rpmdbSetIteratorRewrite(mi, 1);
537 while ((h = rpmdbNextIterator(mi)) != NULL) {
544 if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
547 prev = rpmdbGetIteratorOffset(mi);
549 while (sfi->otherPkg && sfi->otherPkg == prev) {
550 assert(sfi->otherFileNum < count);
551 if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
552 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
554 /* Modified header will be rewritten. */
556 xx = rpmdbSetIteratorModified(mi, modified);
563 mi = rpmdbFreeIterator(mi);
569 * Create directory if it does not exist, make sure path is writable.
570 * @note This will only create last component of directory path.
571 * @param dpath directory path
572 * @param dname directory use
573 * @return rpmRC return code
575 static rpmRC chkdir (const char * dpath, const char * dname)
576 /*@globals fileSystem@*/
577 /*@modifies fileSystem @*/
582 if ((rc = Stat(dpath, &st)) < 0) {
583 int ut = urlPath(dpath, NULL);
592 rc = Mkdir(dpath, 0755);
598 rpmError(RPMERR_CREATE, _("cannot create %%%s %s\n"),
603 if ((rc = Access(dpath, W_OK))) {
604 rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"), dname, dpath);
610 rpmRC rpmInstallSourcePackage(const char * rootDir, FD_t fd,
611 const char ** specFilePtr,
612 rpmCallbackFunction notify, rpmCallbackData notifyData,
616 rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
617 TFI_t fi = xcalloc(sizeof(*fi), 1);
618 const char * _sourcedir = NULL;
619 const char * _specdir = NULL;
620 const char * specFile = NULL;
631 /*@-temptrans -assignexpose@*/
632 ts->notifyData = notifyData;
633 /*@=temptrans =assignexpose@*/
635 /*@-mustmod@*/ /* LCL: segfault */
636 rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
642 rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
647 (void) rpmtransAddPackage(ts, h, fd, NULL, 0, NULL);
648 if (ts->addedPackages.list == NULL) { /* XXX can't happen */
654 fi->ap = ts->addedPackages.list;
657 hfd = (fi->hfd ? fi->hfd : headerFreeData);
658 h = headerFree(h); /* XXX reference held by transaction set */
660 (void) rpmInstallLoadMacros(fi, fi->h);
662 memset(psm, 0, sizeof(*psm));
668 if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
669 *cookie = xstrdup(*cookie);
672 /* XXX FIXME: can't do endian neutral MD5 verification yet. */
673 fi->fmd5s = hfd(fi->fmd5s, -1);
675 /* XXX FIXME: don't do per-file mapping, force global flags. */
676 fi->fmapflags = _free(fi->fmapflags);
677 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
684 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
685 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
686 for (i = 0; i < fi->fc; i++) {
687 fi->fuids[i] = fi->uid;
688 fi->fgids[i] = fi->gid;
691 for (i = 0; i < fi->fc; i++) {
692 fi->actions[i] = FA_CREATE;
695 rpmBuildFileList(fi->h, &fi->apath, NULL);
698 if (headerIsEntry(fi->h, RPMTAG_COOKIE))
699 for (i = 0; i < fi->fc; i++)
700 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
703 /* Find the spec file by name. */
704 for (i = 0; i < fi->fc; i++) {
705 const char * t = fi->apath[i];
706 t += strlen(fi->apath[i]) - 5;
707 if (!strcmp(t, ".spec")) break;
711 _sourcedir = rpmGenPath(ts->rootDir, "%{_sourcedir}", "");
712 rc = chkdir(_sourcedir, "sourcedir");
718 _specdir = rpmGenPath(ts->rootDir, "%{_specdir}", "");
719 rc = chkdir(_specdir, "specdir");
725 /* Build dnl/dil with {_sourcedir, _specdir} as values. */
727 int speclen = strlen(_specdir) + 2;
728 int sourcelen = strlen(_sourcedir) + 2;
731 fi->dnl = hfd(fi->dnl, -1);
734 fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl) + fi->fc * sizeof(*fi->dil) +
735 speclen + sourcelen);
736 fi->dil = (int *)(fi->dnl + fi->dc);
737 memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
739 /*@-dependenttrans@*/
740 fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
741 fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
742 /*@=dependenttrans@*/
743 (void) stpcpy( stpcpy(t, _specdir), "/");
745 t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
746 (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
749 rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
754 psm->goal = PSM_PKGINSTALL;
756 /*@-compmempass@*/ /* FIX: psm->fi->dnl should be owned. */
757 rc = psmStage(psm, PSM_PROCESS);
759 (void) psmStage(psm, PSM_FINI);
762 if (rc) rc = RPMRC_FAIL;
765 if (specFilePtr && specFile && rc == RPMRC_OK)
766 *specFilePtr = specFile;
768 specFile = _free(specFile);
770 _specdir = _free(_specdir);
771 _sourcedir = _free(_sourcedir);
773 if (h) h = headerFree(h);
779 ts = rpmtransFree(ts);
784 /*@observer@*/ /*@unchecked@*/
785 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
788 * Return scriptlet name from tag.
789 * @param tag scriptlet tag
790 * @return name of scriptlet
792 static /*@observer@*/ const char * const tag2sln(int tag)
796 case RPMTAG_PREIN: return "%pre";
797 case RPMTAG_POSTIN: return "%post";
798 case RPMTAG_PREUN: return "%preun";
799 case RPMTAG_POSTUN: return "%postun";
800 case RPMTAG_VERIFYSCRIPT: return "%verify";
802 return "%unknownscript";
806 * Run scriptlet with args.
808 * Run a script with an interpreter. If the interpreter is not specified,
809 * /bin/sh will be used. If the interpreter is /bin/sh, then the args from
810 * the header will be ignored, passing instead arg1 and arg2.
812 * @param psm package state machine data
814 * @param sln name of scriptlet section
815 * @param progArgc no. of args from header
816 * @param progArgv args from header, progArgv[0] is the interpreter to use
817 * @param script scriptlet from header
818 * @param arg1 no. instances of package installed after scriptlet exec
820 * @param arg2 ditto, but for the target package
821 * @return 0 on success, 1 on error
823 static int runScript(PSM_t psm, Header h,
825 int progArgc, const char ** progArgv,
826 const char * script, int arg1, int arg2)
827 /*@globals rpmGlobalMacroContext,
828 fileSystem, internalState@*/
829 /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
831 const rpmTransactionSet ts = psm->ts;
834 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
835 const char ** argv = NULL;
837 const char ** prefixes = NULL;
840 const char * oldPrefix;
843 char * prefixBuf = NULL;
846 const char * fn = NULL;
848 int freePrefixes = 0;
851 const char *n, *v, *r;
853 if (!progArgv && !script)
857 argv = alloca(5 * sizeof(*argv));
861 argv = alloca((progArgc + 4) * sizeof(*argv));
862 memcpy(argv, progArgv, progArgc * sizeof(*argv));
866 xx = headerNVR(h, &n, &v, &r);
867 if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
869 } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
870 prefixes = &oldPrefix;
877 for (i = 0; i < numPrefixes; i++) {
878 len = strlen(prefixes[i]);
879 if (len > maxPrefixLength) maxPrefixLength = len;
881 prefixBuf = alloca(maxPrefixLength + 50);
886 if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) {
887 if (freePrefixes) free(prefixes);
893 (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
895 static const char set_x[] = "set -x\n";
896 xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
899 xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
902 { const char * sn = fn;
903 if (!ts->chrootDone &&
904 !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0'))
906 sn += strlen(ts->rootDir)-1;
912 char *av = alloca(20);
913 sprintf(av, "%d", arg1);
917 char *av = alloca(20);
918 sprintf(av, "%d", arg2);
925 if (ts->scriptFd != NULL) {
926 if (rpmIsVerbose()) {
927 out = fdDup(Fileno(ts->scriptFd));
929 out = Fopen("/dev/null", "w.fdio");
931 out = fdDup(Fileno(ts->scriptFd));
935 out = fdDup(STDOUT_FILENO);
937 out = fdLink(out, "runScript persist");
940 if (out == NULL) return 1; /* XXX can't happen */
942 if (!(child = fork())) {
943 const char * rootDir;
946 pipes[0] = pipes[1] = 0;
947 /* make stdin inaccessible */
949 xx = close(pipes[1]);
950 xx = dup2(pipes[0], STDIN_FILENO);
951 xx = close(pipes[0]);
954 if (ts->scriptFd != NULL) {
955 int sfdno = Fileno(ts->scriptFd);
956 int ofdno = Fileno(out);
957 if (sfdno != STDERR_FILENO)
958 xx = dup2(sfdno, STDERR_FILENO);
959 if (ofdno != STDOUT_FILENO)
960 xx = dup2(ofdno, STDOUT_FILENO);
961 /* make sure we don't close stdin/stderr/stdout by mistake! */
962 if (ofdno > STDERR_FILENO && ofdno != sfdno) {
965 if (sfdno > STDERR_FILENO) {
966 xx = Fclose (ts->scriptFd);
972 { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
973 const char *path = SCRIPT_PATH;
975 if (ipath && ipath[5] != '%')
980 ipath = _free(ipath);
985 for (i = 0; i < numPrefixes; i++) {
986 sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
987 xx = doputenv(prefixBuf);
989 /* backwards compatibility */
991 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
992 xx = doputenv(prefixBuf);
996 if ((rootDir = ts->rootDir) != NULL) /* XXX can't happen */
997 switch(urlIsURL(rootDir)) {
999 rootDir += sizeof("file://") - 1;
1000 rootDir = strchr(rootDir, '/');
1002 case URL_IS_UNKNOWN:
1003 if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) {
1004 /*@-superuser -noeffect @*/
1005 xx = chroot(rootDir);
1006 /*@=superuser =noeffect @*/
1009 xx = execv(argv[0], (char *const *)argv);
1019 if (waitpid(child, &status, 0) < 0) {
1020 rpmError(RPMERR_SCRIPT,
1021 _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"),
1022 sln, n, v, r, strerror (errno));
1023 /* XXX what to do here? */
1026 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
1027 rpmError(RPMERR_SCRIPT,
1028 _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"),
1029 sln, n, v, r, WEXITSTATUS(status));
1034 if (freePrefixes) prefixes = hfd(prefixes, ipt);
1036 xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
1050 * Retrieve and run scriptlet from header.
1051 * @param psm package state machine data
1052 * @return rpmRC return code
1054 static rpmRC runInstScript(PSM_t psm)
1055 /*@globals rpmGlobalMacroContext,
1056 fileSystem, internalState @*/
1057 /*@modifies psm, rpmGlobalMacroContext,
1058 fileSystem, internalState @*/
1061 HGE_t hge = fi->hge;
1062 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1063 void ** programArgv;
1066 rpmTagType ptt, stt;
1067 const char * script;
1068 rpmRC rc = RPMRC_OK;
1072 * headerGetEntry() sets the data pointer to NULL if the entry does
1075 xx = hge(fi->h, psm->progTag, &ptt, (void **) &programArgv, &programArgc);
1076 xx = hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
1079 if (programArgv && ptt == RPM_STRING_TYPE) {
1080 argv = alloca(sizeof(*argv));
1081 *argv = (const char *) programArgv;
1083 argv = (const char **) programArgv;
1087 rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), programArgc, argv,
1088 script, psm->scriptArg, -1);
1090 programArgv = hfd(programArgv, ptt);
1091 script = hfd(script, stt);
1096 * @param psm package state machine data
1100 * @param triggersAlreadyRun
1103 static int handleOneTrigger(PSM_t psm, Header sourceH, Header triggeredH,
1104 int arg2, unsigned char * triggersAlreadyRun)
1105 /*@globals rpmGlobalMacroContext,
1106 fileSystem, internalState@*/
1107 /*@modifies psm, *triggersAlreadyRun, rpmGlobalMacroContext,
1108 fileSystem, internalState @*/
1110 const rpmTransactionSet ts = psm->ts;
1112 HGE_t hge = fi->hge;
1113 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1114 const char ** triggerNames;
1115 const char ** triggerEVR;
1116 const char ** triggerScripts;
1117 const char ** triggerProgs;
1118 int_32 * triggerFlags;
1119 int_32 * triggerIndices;
1120 rpmTagType tnt, tvt, tft;
1121 const char * triggerPackageName;
1122 const char * sourceName;
1124 rpmRC rc = RPMRC_OK;
1128 if (!( hge(triggeredH, RPMTAG_TRIGGERNAME, &tnt,
1129 (void **) &triggerNames, &numTriggers) &&
1130 hge(triggeredH, RPMTAG_TRIGGERFLAGS, &tft,
1131 (void **) &triggerFlags, NULL) &&
1132 hge(triggeredH, RPMTAG_TRIGGERVERSION, &tvt,
1133 (void **) &triggerEVR, NULL))
1137 xx = headerNVR(sourceH, &sourceName, NULL, NULL);
1139 for (i = 0; i < numTriggers; i++) {
1140 rpmTagType tit, tst, tpt;
1142 if (!(triggerFlags[i] & psm->sense)) continue;
1143 if (strcmp(triggerNames[i], sourceName)) continue;
1146 * For some reason, the TRIGGERVERSION stuff includes the name of
1147 * the package which the trigger is based on. We need to skip
1148 * over that here. I suspect that we'll change our minds on this
1149 * and remove that, so I'm going to just 'do the right thing'.
1151 skip = strlen(triggerNames[i]);
1152 if (!strncmp(triggerEVR[i], triggerNames[i], skip) &&
1153 (triggerEVR[i][skip] == '-'))
1158 if (!headerMatchesDepFlags(sourceH, triggerNames[i],
1159 triggerEVR[i] + skip, triggerFlags[i]))
1162 if (!( hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
1163 (void **) &triggerIndices, NULL) &&
1164 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
1165 (void **) &triggerScripts, NULL) &&
1166 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
1167 (void **) &triggerProgs, NULL))
1171 xx = headerNVR(triggeredH, &triggerPackageName, NULL, NULL);
1176 arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName);
1178 /* XXX W2DO? same as "execution of script failed" */
1181 arg1 += psm->countCorrection;
1182 index = triggerIndices[i];
1183 if (triggersAlreadyRun == NULL ||
1184 triggersAlreadyRun[index] == 0)
1186 rc = runScript(psm, triggeredH, "%trigger", 1,
1187 triggerProgs + index, triggerScripts[index],
1189 if (triggersAlreadyRun != NULL)
1190 triggersAlreadyRun[index] = 1;
1195 triggerIndices = hfd(triggerIndices, tit);
1196 triggerScripts = hfd(triggerScripts, tst);
1197 triggerProgs = hfd(triggerProgs, tpt);
1200 * Each target/source header pair can only result in a single
1206 triggerNames = hfd(triggerNames, tnt);
1207 triggerFlags = hfd(triggerFlags, tft);
1208 triggerEVR = hfd(triggerEVR, tvt);
1214 * Run trigger scripts in the database that are fired by this header.
1215 * @param psm package state machine data
1216 * @return 0 on success, 1 on error
1218 static int runTriggers(PSM_t psm)
1219 /*@globals rpmGlobalMacroContext,
1220 fileSystem, internalState @*/
1221 /*@modifies psm, rpmGlobalMacroContext,
1222 fileSystem, internalState @*/
1224 const rpmTransactionSet ts = psm->ts;
1227 rpmRC rc = RPMRC_OK;
1229 numPackage = rpmdbCountPackages(ts->rpmdb, fi->name) + psm->countCorrection;
1233 { Header triggeredH;
1234 rpmdbMatchIterator mi;
1235 int countCorrection = psm->countCorrection;
1237 psm->countCorrection = 0;
1238 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, fi->name, 0);
1239 while((triggeredH = rpmdbNextIterator(mi)) != NULL) {
1240 rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
1243 mi = rpmdbFreeIterator(mi);
1244 psm->countCorrection = countCorrection;
1251 * Run triggers from this header that are fired by headers in the database.
1252 * @param psm package state machine data
1253 * @return 0 on success, 1 on error
1255 static int runImmedTriggers(PSM_t psm)
1256 /*@globals rpmGlobalMacroContext,
1257 fileSystem, internalState @*/
1258 /*@modifies psm, rpmGlobalMacroContext,
1259 fileSystem, internalState @*/
1261 const rpmTransactionSet ts = psm->ts;
1263 HGE_t hge = fi->hge;
1264 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1265 const char ** triggerNames;
1267 int_32 * triggerIndices;
1268 rpmTagType tnt, tit;
1269 int numTriggerIndices;
1270 unsigned char * triggersRun;
1271 rpmRC rc = RPMRC_OK;
1273 if (!( hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
1274 (void **) &triggerNames, &numTriggers) &&
1275 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
1276 (void **) &triggerIndices, &numTriggerIndices))
1280 triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
1281 memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
1283 { Header sourceH = NULL;
1286 for (i = 0; i < numTriggers; i++) {
1287 rpmdbMatchIterator mi;
1289 if (triggersRun[triggerIndices[i]] != 0) continue;
1291 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, triggerNames[i], 0);
1293 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
1294 rc |= handleOneTrigger(psm, sourceH, fi->h,
1295 rpmdbGetIteratorCount(mi),
1299 mi = rpmdbFreeIterator(mi);
1302 triggerIndices = hfd(triggerIndices, tit);
1303 triggerNames = hfd(triggerNames, tnt);
1307 /*@observer@*/ static const char *const pkgStageString(pkgStage a)
1311 case PSM_UNKNOWN: return "unknown";
1313 case PSM_PKGINSTALL: return " install";
1314 case PSM_PKGERASE: return " erase";
1315 case PSM_PKGCOMMIT: return " commit";
1316 case PSM_PKGSAVE: return "repackage";
1318 case PSM_INIT: return "init";
1319 case PSM_PRE: return "pre";
1320 case PSM_PROCESS: return "process";
1321 case PSM_POST: return "post";
1322 case PSM_UNDO: return "undo";
1323 case PSM_FINI: return "fini";
1325 case PSM_CREATE: return "create";
1326 case PSM_NOTIFY: return "notify";
1327 case PSM_DESTROY: return "destroy";
1328 case PSM_COMMIT: return "commit";
1330 case PSM_CHROOT_IN: return "chrootin";
1331 case PSM_CHROOT_OUT: return "chrootout";
1332 case PSM_SCRIPT: return "script";
1333 case PSM_TRIGGERS: return "triggers";
1334 case PSM_IMMED_TRIGGERS: return "immedtriggers";
1336 case PSM_RPMIO_FLAGS: return "rpmioflags";
1338 case PSM_RPMDB_LOAD: return "rpmdbload";
1339 case PSM_RPMDB_ADD: return "rpmdbadd";
1340 case PSM_RPMDB_REMOVE: return "rpmdbremove";
1342 default: return "???";
1348 * @todo Packages w/o files never get a callback, hence don't get displayed
1349 * on install with -v.
1351 int psmStage(PSM_t psm, pkgStage stage)
1353 const rpmTransactionSet ts = psm->ts;
1355 HGE_t hge = fi->hge;
1356 HME_t hme = fi->hme;
1357 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1367 rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"),
1368 psm->stepName, fi->name, fi->version, fi->release,
1369 fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST));
1372 * When we run scripts, we pass an argument which is the number of
1373 * versions of this package that will be installed when we are
1376 psm->npkgs_installed = rpmdbCountPackages(ts->rpmdb, fi->name);
1377 if (psm->npkgs_installed < 0) {
1382 if (psm->goal == PSM_PKGINSTALL) {
1383 psm->scriptArg = psm->npkgs_installed + 1;
1385 assert(psm->mi == NULL);
1386 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, fi->name, 0);
1387 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION,
1388 RPMMIRE_DEFAULT, fi->version);
1389 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE,
1390 RPMMIRE_DEFAULT, fi->release);
1392 while ((psm->oh = rpmdbNextIterator(psm->mi))) {
1393 fi->record = rpmdbGetIteratorOffset(psm->mi);
1394 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB)
1395 psm->oh = headerCopy(psm->oh);
1398 /*@loopbreak@*/ break;
1400 psm->mi = rpmdbFreeIterator(psm->mi);
1403 if (fi->fc > 0 && fi->fstates == NULL) {
1404 fi->fstates = xmalloc(sizeof(*fi->fstates) * fi->fc);
1405 memset(fi->fstates, RPMFILE_STATE_NORMAL, fi->fc);
1408 if (fi->fc <= 0) break;
1409 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1412 * Old format relocateable packages need the entire default
1413 * prefix stripped to form the cpio list, while all other packages
1414 * need the leading / stripped.
1417 rc = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
1418 fi->striplen = (rc ? strlen(p) + 1 : 1);
1421 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
1423 if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
1424 buildOrigFileList(fi->h, &fi->apath, NULL);
1426 rpmBuildFileList(fi->h, &fi->apath, NULL);
1428 if (fi->fuser == NULL)
1429 xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
1430 (void **) &fi->fuser, NULL);
1431 if (fi->fgroup == NULL)
1432 xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
1433 (void **) &fi->fgroup, NULL);
1434 if (fi->fuids == NULL)
1435 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
1436 if (fi->fgids == NULL)
1437 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
1440 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1441 psm->scriptArg = psm->npkgs_installed - 1;
1443 /* Retrieve installed header. */
1444 rc = psmStage(psm, PSM_RPMDB_LOAD);
1446 if (psm->goal == PSM_PKGSAVE) {
1447 /* Open output package for writing. */
1448 { const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
1449 const char * pkgbn =
1450 headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
1453 psm->pkgURL = rpmGenPath("%{?_repackage_root:%{_repackage_root}}",
1454 "%{?_repackage_dir:%{_repackage_dir}}",
1456 pkgbn = _free(pkgbn);
1457 (void) urlPath(psm->pkgURL, &psm->pkgfn);
1458 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
1459 if (psm->fd == NULL || Ferror(psm->fd)) {
1467 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1469 /* Change root directory if requested and not already done. */
1470 rc = psmStage(psm, PSM_CHROOT_IN);
1472 if (psm->goal == PSM_PKGINSTALL) {
1473 psm->scriptTag = RPMTAG_PREIN;
1474 psm->progTag = RPMTAG_PREINPROG;
1476 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
1477 /* XXX FIXME: implement %triggerprein. */
1480 if (!(ts->transFlags & RPMTRANS_FLAG_NOPRE)) {
1481 rc = psmStage(psm, PSM_SCRIPT);
1483 rpmError(RPMERR_SCRIPT,
1484 _("%s: %s scriptlet failed (%d), skipping %s-%s-%s\n"),
1485 psm->stepName, tag2sln(psm->scriptTag), rc,
1486 fi->name, fi->version, fi->release);
1492 if (psm->goal == PSM_PKGERASE) {
1493 psm->scriptTag = RPMTAG_PREUN;
1494 psm->progTag = RPMTAG_PREUNPROG;
1495 psm->sense = RPMSENSE_TRIGGERUN;
1496 psm->countCorrection = -1;
1498 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERUN)) {
1499 /* Run triggers in other package(s) this package sets off. */
1500 rc = psmStage(psm, PSM_TRIGGERS);
1503 /* Run triggers in this package other package(s) set off. */
1504 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
1508 if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
1509 rc = psmStage(psm, PSM_SCRIPT);
1511 if (psm->goal == PSM_PKGSAVE) {
1512 /* Regenerate original header. */
1516 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
1517 psm->oh = headerCopyLoad(uh);
1520 psm->oh = headerLink(fi->h);
1524 /* Add remove transaction id to header. */
1526 { int_32 tid = ts->id;
1527 xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
1528 RPM_INT32_TYPE, &tid, 1);
1531 /* Retrieve type of payload compression. */
1532 /*@-nullstate@*/ /* FIX: psm->oh may be NULL */
1533 rc = psmStage(psm, PSM_RPMIO_FLAGS);
1536 /* Write the lead section into the package. */
1539 struct rpmlead lead;
1542 rpmGetArchInfo(NULL, &archnum);
1543 rpmGetOsInfo(NULL, &osnum);
1546 memset(&lead, 0, sizeof(lead));
1547 /* XXX Set package version conditioned on noDirTokens. */
1550 lead.type = RPMLEAD_BINARY;
1551 lead.archnum = archnum;
1553 lead.signature_type = RPMSIGTYPE_HEADERSIG;
1556 sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
1557 strncpy(lead.name, buf, sizeof(lead.name));
1560 rc = writeLead(psm->fd, &lead);
1562 rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
1563 Fstrerror(psm->fd));
1569 /* Write the signature section into the package. */
1570 { Header sig = headerRegenSigHeader(fi->h);
1571 rc = rpmWriteSignature(psm->fd, sig);
1572 sig = rpmFreeSignature(sig);
1576 /* Write the metadata section into the package. */
1577 rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
1582 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1584 if (psm->goal == PSM_PKGINSTALL) {
1585 struct availablePackage * alp = fi->ap;
1588 if (fi->fc <= 0) break;
1589 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1591 for (i = 0; i < fi->fc; i++) {
1597 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
1598 rpmMessage(RPMMESS_WARNING,
1599 _("user %s does not exist - using root\n"),
1602 /* XXX this diddles header memory. */
1603 fi->fmodes[i] &= ~S_ISUID; /* turn off the suid bit */
1606 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
1607 rpmMessage(RPMMESS_WARNING,
1608 _("group %s does not exist - using root\n"),
1611 /* XXX this diddles header memory. */
1612 fi->fmodes[i] &= ~S_ISGID; /* turn off the sgid bit */
1614 if (fi->fuids) fi->fuids[i] = uid;
1615 if (fi->fgids) fi->fgids[i] = gid;
1618 /* Retrieve type of payload compression. */
1619 rc = psmStage(psm, PSM_RPMIO_FLAGS);
1621 if (alp->fd == NULL) { /* XXX can't happen */
1625 /*@-nullpass@*/ /* LCL: alp->fd != NULL here. */
1626 psm->cfd = Fdopen(fdDup(Fileno(alp->fd)), psm->rpmio_flags);
1628 if (psm->cfd == NULL) { /* XXX can't happen */
1633 rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
1634 psm->cfd, NULL, &psm->failedFile);
1635 xx = fsmTeardown(fi->fsm);
1637 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1638 xx = Fclose(psm->cfd);
1641 errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1645 rc = psmStage(psm, PSM_COMMIT);
1648 rpmError(RPMERR_CPIO,
1649 _("unpacking of archive failed%s%s: %s\n"),
1650 (psm->failedFile != NULL ? _(" on file ") : ""),
1651 (psm->failedFile != NULL ? psm->failedFile : ""),
1656 psm->what = RPMCALLBACK_INST_PROGRESS;
1657 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1658 psm->total = psm->amount;
1659 xx = psmStage(psm, PSM_NOTIFY);
1661 if (psm->goal == PSM_PKGERASE) {
1663 if (fi->fc <= 0) break;
1664 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
1665 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
1667 psm->what = RPMCALLBACK_UNINST_START;
1668 psm->amount = fi->fc; /* XXX W2DO? looks wrong. */
1669 psm->total = fi->fc;
1670 xx = psmStage(psm, PSM_NOTIFY);
1672 rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
1673 NULL, NULL, &psm->failedFile);
1674 xx = fsmTeardown(fi->fsm);
1676 psm->what = RPMCALLBACK_UNINST_STOP;
1677 psm->amount = 0; /* XXX W2DO? looks wrong. */
1678 psm->total = fi->fc;
1679 xx = psmStage(psm, PSM_NOTIFY);
1682 if (psm->goal == PSM_PKGSAVE) {
1683 fileAction * actions = fi->actions;
1684 fileAction action = fi->action;
1686 fi->action = FA_COPYOUT;
1689 if (psm->fd == NULL) { /* XXX can't happen */
1693 /*@-nullpass@*/ /* LCL: psm->fd != NULL here. */
1694 xx = Fflush(psm->fd);
1695 psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
1697 if (psm->cfd == NULL) { /* XXX can't happen */
1702 rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
1703 NULL, &psm->failedFile);
1704 xx = fsmTeardown(fi->fsm);
1706 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1707 xx = Fclose(psm->cfd);
1713 fi->action = action;
1714 fi->actions = actions;
1718 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1720 if (psm->goal == PSM_PKGINSTALL) {
1721 int_32 installTime = (int_32) time(NULL);
1723 if (fi->fstates != NULL && fi->fc > 0)
1724 xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
1725 fi->fstates, fi->fc);
1727 xx = headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
1730 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB) {
1731 uint_32 multiLib, * newMultiLib, * p;
1733 if (hge(fi->h, RPMTAG_MULTILIBS, NULL,
1734 (void **) &newMultiLib, NULL) &&
1735 hge(psm->oh, RPMTAG_MULTILIBS, NULL,
1736 (void **) &p, NULL))
1739 multiLib |= *newMultiLib;
1740 xx = hme(psm->oh, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
1743 rc = mergeFiles(fi, psm->oh, fi->h);
1749 * If this package has already been installed, remove it from
1750 * the database before adding the new one.
1752 if (fi->record && !(ts->transFlags & RPMTRANS_FLAG_APPLYONLY)) {
1753 rc = psmStage(psm, PSM_RPMDB_REMOVE);
1757 rc = psmStage(psm, PSM_RPMDB_ADD);
1760 psm->scriptTag = RPMTAG_POSTIN;
1761 psm->progTag = RPMTAG_POSTINPROG;
1762 psm->sense = RPMSENSE_TRIGGERIN;
1763 psm->countCorrection = 0;
1765 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOST)) {
1766 rc = psmStage(psm, PSM_SCRIPT);
1769 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERIN)) {
1770 /* Run triggers in other package(s) this package sets off. */
1771 rc = psmStage(psm, PSM_TRIGGERS);
1774 /* Run triggers in this package other package(s) set off. */
1775 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
1779 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
1780 rc = markReplacedFiles(psm);
1783 if (psm->goal == PSM_PKGERASE) {
1785 psm->scriptTag = RPMTAG_POSTUN;
1786 psm->progTag = RPMTAG_POSTUNPROG;
1787 psm->sense = RPMSENSE_TRIGGERPOSTUN;
1788 psm->countCorrection = -1;
1790 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOSTUN)) {
1791 rc = psmStage(psm, PSM_SCRIPT);
1792 /* XXX WTFO? postun failures don't cause erasure failure. */
1795 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
1796 /* Run triggers in other package(s) this package sets off. */
1797 rc = psmStage(psm, PSM_TRIGGERS);
1801 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
1802 rc = psmStage(psm, PSM_RPMDB_REMOVE);
1804 if (psm->goal == PSM_PKGSAVE) {
1807 /* Restore root directory if changed. */
1808 xx = psmStage(psm, PSM_CHROOT_OUT);
1813 /* Restore root directory if changed. */
1814 xx = psmStage(psm, PSM_CHROOT_OUT);
1817 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1818 xx = Fclose(psm->fd);
1825 if (psm->goal == PSM_PKGSAVE) {
1827 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
1828 (psm->pkgURL ? psm->pkgURL : "???"));
1833 if (psm->failedFile)
1834 rpmError(RPMERR_CPIO,
1835 _("%s failed on file %s: %s\n"),
1836 psm->stepName, psm->failedFile, cpioStrerror(rc));
1838 rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
1839 psm->stepName, cpioStrerror(rc));
1842 if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE))
1843 fi->h = headerFree(fi->h);
1844 psm->oh = headerFree(psm->oh);
1845 psm->pkgURL = _free(psm->pkgURL);
1846 psm->rpmio_flags = _free(psm->rpmio_flags);
1847 psm->failedFile = _free(psm->failedFile);
1849 fi->fgids = _free(fi->fgids);
1850 fi->fuids = _free(fi->fuids);
1851 fi->fgroup = hfd(fi->fgroup, -1);
1852 fi->fuser = hfd(fi->fuser, -1);
1853 fi->apath = _free(fi->apath);
1854 fi->fstates = _free(fi->fstates);
1857 case PSM_PKGINSTALL:
1862 psm->stepName = pkgStageString(stage);
1864 rc = psmStage(psm, PSM_INIT);
1865 if (!rc) rc = psmStage(psm, PSM_PRE);
1866 if (!rc) rc = psmStage(psm, PSM_PROCESS);
1867 if (!rc) rc = psmStage(psm, PSM_POST);
1868 xx = psmStage(psm, PSM_FINI);
1876 if (ts && ts->notify) {
1877 /*@-noeffectuncon @*/ /* FIX: check rc */
1878 (void) ts->notify(fi->h, psm->what, psm->amount, psm->total,
1879 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
1880 /*@=noeffectuncon @*/
1886 if (!(ts->transFlags & RPMTRANS_FLAG_PKGCOMMIT)) break;
1887 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
1889 rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
1890 NULL, NULL, &psm->failedFile);
1891 xx = fsmTeardown(fi->fsm);
1895 /* Change root directory if requested and not already done. */
1896 if (ts->rootDir && !ts->chrootDone && !psm->chrootDone) {
1897 static int _loaded = 0;
1900 * This loads all of the name services libraries, in case we
1901 * don't have access to them in the chroot().
1904 (void)getpwnam("root");
1911 rc = chroot(ts->rootDir);
1913 psm->chrootDone = ts->chrootDone = 1;
1914 if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 1;
1917 chroot_prefix = ts->rootDir;
1922 case PSM_CHROOT_OUT:
1923 /* Restore root directory if changed. */
1924 if (psm->chrootDone) {
1928 psm->chrootDone = ts->chrootDone = 0;
1929 if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 0;
1931 chroot_prefix = NULL;
1933 xx = chdir(ts->currDir);
1937 rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"),
1938 psm->stepName, tag2sln(psm->scriptTag));
1939 rc = runInstScript(psm);
1942 /* Run triggers in other package(s) this package sets off. */
1943 rc = runTriggers(psm);
1945 case PSM_IMMED_TRIGGERS:
1946 /* Run triggers in this package other package(s) set off. */
1947 rc = runImmedTriggers(psm);
1950 case PSM_RPMIO_FLAGS:
1951 { const char * payload_compressor = NULL;
1954 if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
1955 (void **) &payload_compressor, NULL))
1956 payload_compressor = "gzip";
1957 psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
1959 t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
1960 if (!strcmp(payload_compressor, "gzip"))
1961 t = stpcpy(t, ".gzdio");
1962 if (!strcmp(payload_compressor, "bzip2"))
1963 t = stpcpy(t, ".bzdio");
1967 case PSM_RPMDB_LOAD:
1968 assert(psm->mi == NULL);
1969 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
1970 &fi->record, sizeof(fi->record));
1972 fi->h = rpmdbNextIterator(psm->mi);
1974 fi->h = headerLink(fi->h);
1976 fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
1978 psm->mi = rpmdbFreeIterator(psm->mi);
1979 rc = (fi->h ? RPMRC_OK : RPMRC_FAIL);
1982 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1983 rc = rpmdbAdd(ts->rpmdb, ts->id, fi->h);
1985 case PSM_RPMDB_REMOVE:
1986 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
1987 rc = rpmdbRemove(ts->rpmdb, ts->id, fi->record);
1995 /*@-nullstate@*/ /* FIX: psm->oh and psm->fi->h may be NULL. */