rpm  4.5
psm.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h>
9 #include <header_internal.h>
10 #include <rpmlib.h>
11 #include <rpmmacro.h>
12 #include <rpmurl.h>
13 #include <rpmlua.h>
14 
15 #include "cpio.h"
16 #include "fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */
17 #include "psm.h"
18 
19 #define _RPMEVR_INTERNAL
20 #include "rpmds.h"
21 
22 #define _RPMFI_INTERNAL
23 #include "rpmfi.h"
24 
25 #define _RPMTE_INTERNAL
26 #include "rpmte.h"
27 
28 #define _RPMTS_INTERNAL /* XXX ts->notify */
29 #include "rpmts.h"
30 
31 #include "rpmlead.h" /* writeLead proto */
32 #include "signature.h" /* signature constants */
33 #include "legacy.h" /* XXX rpmfiBuildFNames() */
34 #include "misc.h" /* XXX stripTrailingChar() */
35 #include "rpmdb.h" /* XXX for db_chrootDone */
36 #include "debug.h"
37 
38 #define _PSM_DEBUG 0
39 /*@unchecked@*/
41 /*@unchecked@*/
42 int _psm_threads = 0;
43 
44 /*@access FD_t @*/ /* XXX void ptr args */
45 /*@access rpmpsm @*/
46 
47 /*@access rpmfi @*/
48 /*@access rpmte @*/ /* XXX rpmInstallSourcePackage */
49 /*@access rpmts @*/ /* XXX ts->notify */
50 
51 /*@access rpmluav @*/
52 
53 int rpmVersionCompare(Header first, Header second)
54 {
55  const char * one, * two;
56  int_32 * epochOne, * epochTwo;
57  static int_32 zero = 0;
58  int rc;
59 
60  if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, &epochOne, NULL))
61  epochOne = &zero;
62  if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, &epochTwo, NULL))
63  epochTwo = &zero;
64 
65 /*@-boundsread@*/
66  if (*epochOne < *epochTwo)
67  return -1;
68  else if (*epochOne > *epochTwo)
69  return 1;
70 /*@=boundsread@*/
71 
72  rc = headerGetEntry(first, RPMTAG_VERSION, NULL, &one, NULL);
73  rc = headerGetEntry(second, RPMTAG_VERSION, NULL, &two, NULL);
74 
75  rc = rpmvercmp(one, two);
76  if (rc)
77  return rc;
78 
79  rc = headerGetEntry(first, RPMTAG_RELEASE, NULL, &one, NULL);
80  rc = headerGetEntry(second, RPMTAG_RELEASE, NULL, &two, NULL);
81 
82  return rpmvercmp(one, two);
83 }
84 
90 /*@-bounds@*/
91 static rpmRC markReplacedFiles(const rpmpsm psm)
92  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
93  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
94 {
95  const rpmts ts = psm->ts;
96  rpmfi fi = psm->fi;
97  HGE_t hge = (HGE_t)fi->hge;
98  sharedFileInfo replaced = fi->replaced;
99  sharedFileInfo sfi;
101  Header h;
102  unsigned int * offsets;
103  unsigned int prev;
104  int num, xx;
105 
106  if (!(rpmfiFC(fi) > 0 && fi->replaced))
107  return RPMRC_OK;
108 
109  num = prev = 0;
110  for (sfi = replaced; sfi->otherPkg; sfi++) {
111  if (prev && prev == sfi->otherPkg)
112  continue;
113  prev = sfi->otherPkg;
114  num++;
115  }
116  if (num == 0)
117  return RPMRC_OK;
118 
119  offsets = alloca(num * sizeof(*offsets));
120  offsets[0] = 0;
121  num = prev = 0;
122  for (sfi = replaced; sfi->otherPkg; sfi++) {
123  if (prev && prev == sfi->otherPkg)
124  continue;
125  prev = sfi->otherPkg;
126  offsets[num++] = sfi->otherPkg;
127  }
128 
129  mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
130  xx = rpmdbAppendIterator(mi, offsets, num);
131  xx = rpmdbSetIteratorRewrite(mi, 1);
132 
133  sfi = replaced;
134  while ((h = rpmdbNextIterator(mi)) != NULL) {
135  char * secStates;
136  int modified;
137  int count;
138 
139  modified = 0;
140 
141  if (!hge(h, RPMTAG_FILESTATES, NULL, &secStates, &count))
142  continue;
143 
144  prev = rpmdbGetIteratorOffset(mi);
145  num = 0;
146  while (sfi->otherPkg && sfi->otherPkg == prev) {
147  assert(sfi->otherFileNum < count);
148  if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
149  secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
150  if (modified == 0) {
151  /* Modified header will be rewritten. */
152  modified = 1;
153  xx = rpmdbSetIteratorModified(mi, modified);
154  }
155  num++;
156  }
157  sfi++;
158  }
159  }
160  mi = rpmdbFreeIterator(mi);
161 
162  return RPMRC_OK;
163 }
164 /*@=bounds@*/
165 
167  const char ** specFilePtr, const char ** cookie)
168 {
169  int scareMem = 1; /* XXX fi->h is needed */
170  rpmfi fi = NULL;
171  const char * _sourcedir = NULL;
172  const char * _specdir = NULL;
173  const char * specFile = NULL;
174  HGE_t hge;
175  HFD_t hfd;
176  Header h = NULL;
177  struct rpmpsm_s psmbuf;
178  rpmpsm psm = &psmbuf;
179  int isSource;
180  rpmRC rpmrc;
181  int i;
182 
183  memset(psm, 0, sizeof(*psm));
184  psm->ts = rpmtsLink(ts, "InstallSourcePackage");
185 
186  rpmrc = rpmReadPackageFile(ts, fd, "InstallSourcePackage", &h);
187  switch (rpmrc) {
188  case RPMRC_NOTTRUSTED:
189  case RPMRC_NOKEY:
190  case RPMRC_OK:
191  break;
192  default:
193  goto exit;
194  /*@notreached@*/ break;
195  }
196  if (h == NULL)
197  goto exit;
198 
199  rpmrc = RPMRC_OK;
200 
201  isSource = (headerIsEntry(h, RPMTAG_SOURCERPM) == 0);
202 
203  if (!isSource) {
204  rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
205  rpmrc = RPMRC_FAIL;
206  goto exit;
207  }
208 
209  (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
210 
211  fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
212  h = headerFree(h);
213 
214  if (fi == NULL) { /* XXX can't happen */
215  rpmrc = RPMRC_FAIL;
216  goto exit;
217  }
218 
219 /*@-onlytrans@*/ /* FIX: te reference */
220  fi->te = rpmtsElement(ts, 0);
221 /*@=onlytrans@*/
222  if (fi->te == NULL) { /* XXX can't happen */
223  rpmrc = RPMRC_FAIL;
224  goto exit;
225  }
226 
227 assert(fi->h != NULL);
228  fi->te->h = headerLink(fi->h);
229  fi->te->fd = fdLink(fd, "installSourcePackage");
230  hge = fi->hge;
231  hfd = fi->hfd;
232 
233 /*@i@*/ (void) headerMacrosLoad(fi->h);
234 
235  psm->fi = rpmfiLink(fi, NULL);
236  /*@-assignexpose -usereleased @*/
237  psm->te = fi->te;
238  /*@=assignexpose =usereleased @*/
239 
240  if (cookie) {
241  *cookie = NULL;
242  if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
243  *cookie = xstrdup(*cookie);
244  }
245 
246  /* XXX FIXME: don't do per-file mapping, force global flags. */
247  fi->fmapflags = _free(fi->fmapflags);
249 
250  fi->uid = getuid();
251  fi->gid = getgid();
252  fi->astriplen = 0;
253  fi->striplen = 0;
254 
255  for (i = 0; i < fi->fc; i++)
256  fi->actions[i] = FA_CREATE;
257 
258  i = fi->fc;
259 
260  if (fi->h != NULL) { /* XXX can't happen */
261  rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
262 
263  if (headerIsEntry(fi->h, RPMTAG_COOKIE))
264  for (i = 0; i < fi->fc; i++)
265  if (fi->fflags[i] & RPMFILE_SPECFILE) break;
266  }
267 
268  if (i == fi->fc) {
269  /* Find the spec file by name. */
270  for (i = 0; i < fi->fc; i++) {
271  const char * t = fi->apath[i];
272  t += strlen(fi->apath[i]) - 5;
273  if (!strcmp(t, ".spec")) break;
274  }
275  }
276 
277  _sourcedir = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", "");
278  rpmrc = rpmMkdirPath(_sourcedir, "sourcedir");
279  if (rpmrc) {
280  rpmrc = RPMRC_FAIL;
281  goto exit;
282  }
283  if (Access(_sourcedir, W_OK)) {
284  rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"),
285  "_sourcedir", _sourcedir);
286  rpmrc = RPMRC_FAIL;
287  goto exit;
288  }
289 
290  _specdir = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", "");
291  rpmrc = rpmMkdirPath(_specdir, "specdir");
292  if (rpmrc) {
293  rpmrc = RPMRC_FAIL;
294  goto exit;
295  }
296  if (Access(_specdir, W_OK)) {
297  rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"),
298  "_specdir", _specdir);
299  rpmrc = RPMRC_FAIL;
300  goto exit;
301  }
302 
303  /* Build dnl/dil with {_sourcedir, _specdir} as values. */
304  if (i < fi->fc) {
305  int speclen = strlen(_specdir) + 2;
306  int sourcelen = strlen(_sourcedir) + 2;
307  char * t;
308 
309 /*@i@*/ fi->dnl = hfd(fi->dnl, -1);
310 
311  fi->dc = 2;
312  fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl)
313  + fi->fc * sizeof(*fi->dil)
314  + speclen + sourcelen);
315  /*@-dependenttrans@*/
316  fi->dil = (int *)(fi->dnl + fi->dc);
317  /*@=dependenttrans@*/
318  memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
319  fi->dil[i] = 1;
320  /*@-dependenttrans@*/
321  fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
322  fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
323  /*@=dependenttrans@*/
324  (void) stpcpy( stpcpy(t, _specdir), "/");
325 
326  t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
327  (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
328  specFile = t;
329  } else {
330  rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
331  rpmrc = RPMRC_FAIL;
332  goto exit;
333  }
334 
335  psm->goal = PSM_PKGINSTALL;
336 
337  /*@-compmempass@*/ /* FIX: psm->fi->dnl should be owned. */
338  rpmrc = rpmpsmStage(psm, PSM_PROCESS);
339 
340  (void) rpmpsmStage(psm, PSM_FINI);
341  /*@=compmempass@*/
342 
343  if (rpmrc) rpmrc = RPMRC_FAIL;
344 
345 exit:
346  if (specFilePtr && specFile && rpmrc == RPMRC_OK)
347  *specFilePtr = specFile;
348  else
349  specFile = _free(specFile);
350 
351  _specdir = _free(_specdir);
352  _sourcedir = _free(_sourcedir);
353 
354  psm->fi = rpmfiFree(psm->fi);
355  psm->te = NULL;
356 
357  if (h != NULL) h = headerFree(h);
358 
359  /*@-branchstate@*/
360  if (fi != NULL) {
361  fi->te->h = headerFree(fi->te->h);
362  if (fi->te->fd != NULL)
363  (void) Fclose(fi->te->fd);
364  fi->te->fd = NULL;
365  fi->te = NULL;
366  fi = rpmfiFree(fi);
367  }
368  /*@=branchstate@*/
369 
370  /* XXX nuke the added package(s). */
371  rpmtsClean(ts);
372 
373  psm->ts = rpmtsFree(psm->ts);
374 
375  return rpmrc;
376 }
377 
378 /*@observer@*/ /*@unchecked@*/
379 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
380 
386 static /*@observer@*/ const char * tag2sln(int tag)
387  /*@*/
388 {
389  switch (tag) {
390  case RPMTAG_PRETRANS: return "%pretrans";
391  case RPMTAG_TRIGGERPREIN: return "%triggerprein";
392  case RPMTAG_PREIN: return "%pre";
393  case RPMTAG_POSTIN: return "%post";
394  case RPMTAG_TRIGGERIN: return "%triggerin";
395  case RPMTAG_TRIGGERUN: return "%triggerun";
396  case RPMTAG_PREUN: return "%preun";
397  case RPMTAG_POSTUN: return "%postun";
398  case RPMTAG_POSTTRANS: return "%posttrans";
399  case RPMTAG_TRIGGERPOSTUN: return "%triggerpostun";
400  case RPMTAG_VERIFYSCRIPT: return "%verify";
401  }
402  return "%unknownscript";
403 }
404 
410 static rpmScriptID tag2slx(int tag)
411  /*@*/
412 {
413  switch (tag) {
414  case RPMTAG_PRETRANS: return RPMSCRIPT_PRETRANS;
416  case RPMTAG_PREIN: return RPMSCRIPT_PREIN;
417  case RPMTAG_POSTIN: return RPMSCRIPT_POSTIN;
420  case RPMTAG_PREUN: return RPMSCRIPT_PREUN;
421  case RPMTAG_POSTUN: return RPMSCRIPT_POSTUN;
425  }
426  return RPMSCRIPT_UNKNOWN;
427 }
428 
434 static pid_t psmWait(rpmpsm psm)
435  /*@globals fileSystem, internalState @*/
436  /*@modifies psm, fileSystem, internalState @*/
437 {
438  const rpmts ts = psm->ts;
439  rpmtime_t msecs;
440 
441  (void) rpmsqWait(&psm->sq);
442  msecs = psm->sq.op.usecs/1000;
443  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
444 
446  D_("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
447  psm->stepName, (unsigned)psm->sq.child,
448  (unsigned)psm->sq.reaped, psm->sq.status,
449  (unsigned)msecs/1000, (unsigned)msecs%1000);
450 
451  if (psm->sstates != NULL)
452  { int * ssp = psm->sstates + tag2slx(psm->scriptTag);
453  *ssp &= ~0xffff;
454  *ssp |= (psm->sq.status & 0xffff);
455  *ssp |= RPMSCRIPT_STATE_REAPED;
456  }
457 
458  return psm->sq.reaped;
459 }
460 
461 #ifdef WITH_LUA
462 
465 static rpmRC runLuaScript(rpmpsm psm, Header h, const char *sln,
466  int progArgc, const char **progArgv,
467  const char *script, int arg1, int arg2)
468  /*@globals h_errno, fileSystem, internalState @*/
469  /*@modifies psm, fileSystem, internalState @*/
470 {
471  const rpmts ts = psm->ts;
472  int pwdFdno = -1;
473  int rootFdno = -1;
474  const char *n, *v, *r;
475  rpmRC rc = RPMRC_OK;
476  int i;
477  int xx;
478  rpmlua lua = NULL; /* Global state. */
479  rpmluav var;
480  int * ssp = NULL;
481 
482  if (psm->sstates != NULL)
483  ssp = psm->sstates + tag2slx(psm->scriptTag);
484  if (ssp != NULL)
486 
487  xx = headerNVR(h, &n, &v, &r);
488 
489  /* Save the current working directory. */
490 /*@-nullpass@*/
491  pwdFdno = open(".", O_RDONLY, 0);
492 /*@=nullpass@*/
493 
494  /* Save the current root directory. */
495  rootFdno = open("/", O_RDONLY, 0);
496 
497  /* Get into the chroot. */
498  if (!rpmtsChrootDone(ts)) {
499  const char *rootDir = rpmtsRootDir(ts);
500  /*@-superuser -noeffect @*/
501  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
502  xx = Chroot(rootDir);
503  /*@=superuser =noeffect @*/
504  xx = rpmtsSetChrootDone(ts, 1);
505  }
506  }
507 
508  /* All lua scripts run with CWD == "/". */
509  xx = Chdir("/");
510 
511  /* Create arg variable */
512  rpmluaPushTable(lua, "arg");
513  var = rpmluavNew();
514  rpmluavSetListMode(var, 1);
515 /*@+relaxtypes@*/
516  if (progArgv) {
517  for (i = 0; i < progArgc && progArgv[i]; i++) {
518  rpmluavSetValue(var, RPMLUAV_STRING, progArgv[i]);
519  rpmluaSetVar(lua, var);
520  }
521  }
522  if (arg1 >= 0) {
523  rpmluavSetValueNum(var, arg1);
524  rpmluaSetVar(lua, var);
525  }
526  if (arg2 >= 0) {
527  rpmluavSetValueNum(var, arg2);
528  rpmluaSetVar(lua, var);
529  }
530 /*@=relaxtypes@*/
531 /*@-moduncon@*/
532  var = rpmluavFree(var);
533 /*@=moduncon@*/
534  rpmluaPop(lua);
535 
536  {
537  char buf[BUFSIZ];
538  xx = snprintf(buf, BUFSIZ, "%s(%s-%s-%s)", sln, n, v, r);
539  xx = rpmluaRunScript(lua, script, buf);
540  if (xx == -1)
541  rc = RPMRC_FAIL;
542  if (ssp != NULL) {
543  *ssp &= ~0xffff;
544  *ssp |= (xx & 0xffff);
545  *ssp |= RPMSCRIPT_STATE_REAPED;
546  }
547  }
548 
549  rpmluaDelVar(lua, "arg");
550 
551  /* Get out of chroot. */
552  if (rpmtsChrootDone(ts)) {
553  const char *rootDir = rpmtsRootDir(ts);
554  xx = fchdir(rootFdno);
555  /*@-superuser -noeffect @*/
556  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
557  xx = Chroot(".");
558  /*@=superuser =noeffect @*/
559  xx = rpmtsSetChrootDone(ts, 0);
560  }
561  xx = fchdir(pwdFdno);
562  } else
563  xx = fchdir(pwdFdno);
564 
565  xx = close(rootFdno);
566  xx = close(pwdFdno);
567 
568  return rc;
569 }
570 #endif
571 
574 /*@unchecked@*/
575 static int ldconfig_done = 0;
576 
577 /*@unchecked@*/ /*@observer@*/ /*@null@*/
578 static const char * ldconfig_path = "/sbin/ldconfig";
579 
598 static rpmRC runScript(rpmpsm psm, Header h, const char * sln,
599  int progArgc, const char ** progArgv,
600  const char * script, int arg1, int arg2)
601  /*@globals ldconfig_done, rpmGlobalMacroContext, h_errno,
602  fileSystem, internalState@*/
603  /*@modifies psm, ldconfig_done, rpmGlobalMacroContext,
604  fileSystem, internalState @*/
605 {
606  const rpmts ts = psm->ts;
607  rpmfi fi = psm->fi;
608  HGE_t hge = fi->hge;
609  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
610  const char ** argv = NULL;
611  int argc = 0;
612  const char ** prefixes = NULL;
613  int numPrefixes;
614  rpmTagType ipt;
615  const char * oldPrefix;
616  int maxPrefixLength;
617  int len;
618  char * prefixBuf = NULL;
619  const char * fn = NULL;
620  int xx;
621  int i;
622  int freePrefixes = 0;
623  FD_t scriptFd;
624  FD_t out;
625  rpmRC rc = RPMRC_OK;
626  const char *n, *v, *r, *a;
627  int * ssp = NULL;
628 
629  if (psm->sstates != NULL)
630  ssp = psm->sstates + tag2slx(psm->scriptTag);
631  if (ssp != NULL)
633 
634  if (progArgv == NULL && script == NULL)
635  return rc;
636 
637  /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
638  xx = headerNVR(h, &n, &v, &r);
639  xx = hge(h, RPMTAG_ARCH, NULL, &a, NULL);
640 
641  if (progArgv && strcmp(progArgv[0], "<lua>") == 0) {
642 #ifdef WITH_LUA
644  D_("%s: %s(%s-%s-%s.%s) running <lua> scriptlet.\n"),
645  psm->stepName, tag2sln(psm->scriptTag), n, v, r, a);
646  return runLuaScript(psm, h, sln, progArgc, progArgv,
647  script, arg1, arg2);
648 #else
649  return RPMRC_FAIL;
650 #endif
651  }
652 
653  psm->sq.reaper = 1;
654 
655  /* XXX bash must have functional libtermcap.so.2 */
656  /* if (!strcmp(n, "libtermcap"))
657  * -- always run ldconfig, these checks didn't work when few packages with
658  * shared libs were installed just one after another in the same
659  * transaction */
660  ldconfig_done = 0;
661 
662  /*
663  * If a successor node, and ldconfig was just run, don't bother.
664  */
665  if (ldconfig_path && progArgv != NULL && psm->unorderedSuccessor) {
666  if (ldconfig_done && !strcmp(progArgv[0], ldconfig_path)) {
668  D_("%s: %s(%s-%s-%s.%s) skipping redundant \"%s\".\n"),
669  psm->stepName, tag2sln(psm->scriptTag), n, v, r, a,
670  progArgv[0]);
671  return rc;
672  }
673  }
674 
676  D_("%s: %s(%s-%s-%s.%s) %ssynchronous scriptlet start\n"),
677  psm->stepName, tag2sln(psm->scriptTag), n, v, r, a,
678  (psm->unorderedSuccessor ? "a" : ""));
679 
680  if (!progArgv) {
681  argv = alloca(5 * sizeof(*argv));
682  argv[0] = "/bin/sh";
683  argc = 1;
684  ldconfig_done = 0;
685  } else {
686  argv = alloca((progArgc + 4) * sizeof(*argv));
687  memcpy(argv, progArgv, progArgc * sizeof(*argv));
688  argc = progArgc;
689  ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
690  ? 1 : 0);
691  }
692 
693 #if __ia64__
694  /* XXX This assumes that all interpreters are elf executables. */
695  if ((a != NULL && a[0] == 'i' && a[1] != '\0' && a[2] == '8' && a[3] == '6')
696  && strcmp(argv[0], "/sbin/ldconfig"))
697  {
698  const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL);
699  const char * errstr;
700  char * newPath;
701  char * t;
702 
703  newPath = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
704  fmt = _free(fmt);
705 
706  /* XXX On ia64, change leading /emul/ix86 -> /emul/ia32, ick. */
707  if (newPath != NULL && *newPath != '\0'
708  && strlen(newPath) >= (sizeof("/emul/i386")-1)
709  && newPath[0] == '/' && newPath[1] == 'e' && newPath[2] == 'm'
710  && newPath[3] == 'u' && newPath[4] == 'l' && newPath[5] == '/'
711  && newPath[6] == 'i' && newPath[8] == '8' && newPath[9] == '6')
712  {
713  newPath[7] = 'a';
714  newPath[8] = '3';
715  newPath[9] = '2';
716  }
717 
718  t = alloca(strlen(newPath) + strlen(argv[0]) + 1);
719  *t = '\0';
720  (void) stpcpy( stpcpy(t, newPath), argv[0]);
721  newPath = _free(newPath);
722  argv[0] = t;
723  }
724 #endif
725 
726  if (hge(h, RPMTAG_INSTPREFIXES, &ipt, &prefixes, &numPrefixes)) {
727  freePrefixes = 1;
728  } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, &oldPrefix, NULL)) {
729  prefixes = &oldPrefix;
730  numPrefixes = 1;
731  } else {
732  numPrefixes = 0;
733  }
734 
735  maxPrefixLength = 0;
736  if (prefixes != NULL)
737  for (i = 0; i < numPrefixes; i++) {
738  len = strlen(prefixes[i]);
739  if (len > maxPrefixLength) maxPrefixLength = len;
740  }
741  prefixBuf = alloca(maxPrefixLength + 50);
742 
743  if (script) {
744  const char * rootDir = rpmtsRootDir(ts);
745  FD_t fd;
746 
747  /*@-branchstate@*/
748  if (makeTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd)) {
749  if (prefixes != NULL && freePrefixes) free(prefixes);
750  return RPMRC_FAIL;
751  }
752  /*@=branchstate@*/
753 
754  if (rpmIsDebug() &&
755  (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
756  {
757  static const char set_x[] = "set -x\n";
758  xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
759  }
760 
761  if (ldconfig_path && strstr(script, ldconfig_path) != NULL)
762  ldconfig_done = 1;
763 
764  xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
765  xx = Fclose(fd);
766 
767  { const char * sn = fn;
768  if (!rpmtsChrootDone(ts) && rootDir != NULL &&
769  !(rootDir[0] == '/' && rootDir[1] == '\0'))
770  {
771  sn += strlen(rootDir)-1;
772  }
773  argv[argc++] = sn;
774  }
775 
776  if (arg1 >= 0) {
777  char *av = alloca(20);
778  sprintf(av, "%d", arg1);
779  argv[argc++] = av;
780  }
781  if (arg2 >= 0) {
782  char *av = alloca(20);
783  sprintf(av, "%d", arg2);
784  argv[argc++] = av;
785  }
786  }
787 
788  argv[argc] = NULL;
789 
790  scriptFd = rpmtsScriptFd(ts);
791  if (scriptFd != NULL) {
792  if (rpmIsVerbose()) {
793  out = fdDup(Fileno(scriptFd));
794  } else {
795  out = Fopen("/dev/null", "w.fdio");
796  if (Ferror(out)) {
797  out = fdDup(Fileno(scriptFd));
798  }
799  }
800  } else {
801  out = fdDup(STDOUT_FILENO);
802  }
803  if (out == NULL) return RPMRC_FAIL; /* XXX can't happen */
804 
805  /*@-branchstate@*/
806  xx = rpmsqFork(&psm->sq);
807  if (psm->sq.child == 0) {
808  const char * rootDir;
809  int pipes[2];
810  int flag;
811  int fdno;
812 
813  pipes[0] = pipes[1] = 0;
814  /* make stdin inaccessible */
815  xx = pipe(pipes);
816  xx = close(pipes[1]);
817  xx = dup2(pipes[0], STDIN_FILENO);
818  xx = close(pipes[0]);
819 
820  /* XXX Force FD_CLOEXEC on 1st 100 inherited fdno's. */
821  for (fdno = 3; fdno < 100; fdno++) {
822  flag = fcntl(fdno, F_GETFD);
823  if (flag == -1 || (flag & FD_CLOEXEC))
824  continue;
825  xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
826  /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
827  }
828 
829  if (scriptFd != NULL) {
830  int sfdno = Fileno(scriptFd);
831  int ofdno = Fileno(out);
832  if (sfdno != STDERR_FILENO)
833  xx = dup2(sfdno, STDERR_FILENO);
834  if (ofdno != STDOUT_FILENO)
835  xx = dup2(ofdno, STDOUT_FILENO);
836  /* make sure we don't close stdin/stderr/stdout by mistake! */
837  if (ofdno > STDERR_FILENO && ofdno != sfdno)
838  xx = Fclose (out);
839  if (sfdno > STDERR_FILENO)
840  xx = Fclose (scriptFd);
841  else {
842 /*@-usereleased@*/
843  xx = Fclose(out);
844 /*@=usereleased@*/
845  }
846  }
847 
848  { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
849  const char *path = SCRIPT_PATH;
850 
851  if (ipath && ipath[5] != '%')
852  path = ipath;
853 
854  xx = doputenv(path);
855  /*@-modobserver@*/
856  ipath = _free(ipath);
857  /*@=modobserver@*/
858  }
859 
860  if (prefixes != NULL)
861  for (i = 0; i < numPrefixes; i++) {
862  sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
863  xx = doputenv(prefixBuf);
864 
865  /* backwards compatibility */
866  if (i == 0) {
867  sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
868  xx = doputenv(prefixBuf);
869  }
870  }
871 
872  rootDir = ts->rootDir; /* HACK: rootDir = rpmtsRootDir(ts); instead */
873  if (rootDir != NULL) /* XXX can't happen */
874  switch(urlIsURL(rootDir)) {
875  case URL_IS_PATH:
876  rootDir += sizeof("file://") - 1;
877  rootDir = strchr(rootDir, '/');
878  /*@fallthrough@*/
879  case URL_IS_UNKNOWN:
880  if (!rpmtsChrootDone(ts) &&
881  !(rootDir[0] == '/' && rootDir[1] == '\0'))
882  {
883  /*@-superuser -noeffect @*/
884  xx = Chroot(rootDir);
885  /*@=superuser =noeffect @*/
886  }
887  xx = Chdir("/");
888  rpmMessage(RPMMESS_DEBUG, "%s: %s(%s-%s-%s.%s)\texecv(%s) pid %d\n",
889  psm->stepName, sln, n, v, r, a,
890  argv[0], (unsigned)getpid());
891 
892  /* XXX Don't mtrace into children. */
893  unsetenv("MALLOC_CHECK_");
894 
895  if (ssp != NULL)
896  *ssp |= RPMSCRIPT_STATE_EXEC;
897 
898  /* Permit libselinux to do the scriptlet exec. */
899  if (rpmtsSELinuxEnabled(ts) == 1) {
900  if (ssp != NULL)
901  *ssp |= RPMSCRIPT_STATE_SELINUX;
902 /*@-moduncon@*/
903  xx = rpm_execcon(0, argv[0], argv, environ);
904 /*@=moduncon@*/
905  if (xx != 0)
906  break;
907  }
908 
909 /*@-nullstate@*/
910  xx = execv(argv[0], (char *const *)argv);
911 /*@=nullstate@*/
912  break;
913  case URL_IS_HTTPS:
914  case URL_IS_HTTP:
915  case URL_IS_FTP:
916  case URL_IS_DASH:
917  case URL_IS_HKP:
918  default:
919  break;
920  }
921 
922  if (ssp != NULL)
923  *ssp &= ~RPMSCRIPT_STATE_EXEC;
924 
925  _exit(-1);
926  /*@notreached@*/
927  }
928  /*@=branchstate@*/
929 
930  (void) psmWait(psm);
931 
932  /* XXX filter order dependent multilib "other" arch helper error. */
933  if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
934  if (psm->sq.reaped < 0) {
936  _("%s(%s-%s-%s.%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
937  sln, n, v, r, a, psm->sq.child, psm->sq.reaped, strerror(errno));
938  rc = RPMRC_FAIL;
939  } else
940  if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
941  if (WIFSIGNALED(psm->sq.status)) {
943  _("%s(%s-%s-%s.%s) scriptlet failed, signal %d\n"),
944  sln, n, v, r, a, WTERMSIG(psm->sq.status));
945  } else {
947  _("%s(%s-%s-%s.%s) scriptlet failed, exit status %d\n"),
948  sln, n, v, r, a, WEXITSTATUS(psm->sq.status));
949  }
950  rc = RPMRC_FAIL;
951  }
952  }
953 
954  if (freePrefixes) prefixes = hfd(prefixes, ipt);
955 
956  xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
957 
958  /*@-branchstate@*/
959  if (script) {
960  if (!rpmIsDebug())
961  xx = unlink(fn);
962  fn = _free(fn);
963  }
964  /*@=branchstate@*/
965 
966  return rc;
967 }
968 
975  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
976  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
977 {
978  rpmfi fi = psm->fi;
979  HGE_t hge = fi->hge;
980  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
981  void ** progArgv = NULL;
982  int progArgc;
983  const char * argv0 = NULL;
984  const char ** argv;
985  rpmTagType ptt, stt;
986  const char * script;
987  rpmRC rc = RPMRC_OK;
988  int xx;
989 
990 assert(fi->h != NULL);
991  xx = hge(fi->h, psm->scriptTag, &stt, &script, NULL);
992  xx = hge(fi->h, psm->progTag, &ptt, &progArgv, &progArgc);
993  if (progArgv == NULL && script == NULL)
994  goto exit;
995 
996  /*@-branchstate@*/
997  if (progArgv && ptt == RPM_STRING_TYPE) {
998  argv = alloca(sizeof(*argv));
999  *argv = (const char *) progArgv;
1000  } else {
1001  argv = (const char **) progArgv;
1002  }
1003  /*@=branchstate@*/
1004 
1005  if (argv && argv[0] && argv[0][0] == '%')
1006  argv[0] = argv0 = rpmExpand(argv[0], NULL);
1007 
1008  if (fi->h != NULL) /* XXX can't happen */
1009  rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), progArgc, argv,
1010  script, psm->scriptArg, -1);
1011 
1012 exit:
1013  argv0 = _free(argv0);
1014  progArgv = hfd(progArgv, ptt);
1015  script = hfd(script, stt);
1016  return rc;
1017 }
1018 
1029 static rpmRC handleOneTrigger(const rpmpsm psm,
1030  Header sourceH, Header triggeredH,
1031  int arg2, unsigned char * triggersAlreadyRun)
1032  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState@*/
1033  /*@modifies psm, sourceH, triggeredH, *triggersAlreadyRun,
1034  rpmGlobalMacroContext, fileSystem, internalState @*/
1035 {
1036  int scareMem = 0;
1037  const rpmts ts = psm->ts;
1038  rpmfi fi = psm->fi;
1039  HGE_t hge = fi->hge;
1040  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1041  rpmds trigger = NULL;
1042  const char ** triggerScripts;
1043  const char ** triggerProgs;
1044  int_32 * triggerIndices;
1045  const char * sourceName;
1046  const char * triggerName;
1047  rpmRC rc = RPMRC_OK;
1048  int xx;
1049  int i;
1050 
1051  xx = headerNVR(sourceH, &sourceName, NULL, NULL);
1052  xx = headerNVR(triggeredH, &triggerName, NULL, NULL);
1053 
1054  trigger = rpmdsInit(rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem));
1055  if (trigger == NULL)
1056  return rc;
1057 
1058  (void) rpmdsSetNoPromote(trigger, 1);
1059 
1060  while ((i = rpmdsNext(trigger)) >= 0) {
1061  rpmTagType tit, tst, tpt;
1062  const char * Name;
1063  int_32 Flags = rpmdsFlags(trigger);
1064 
1065  if ((Name = rpmdsN(trigger)) == NULL)
1066  continue; /* XXX can't happen */
1067 
1068  if (strcmp(Name, sourceName))
1069  continue;
1070  if (!(Flags & psm->sense))
1071  continue;
1072 
1073  /*
1074  * XXX Trigger on any provided dependency, not just the package NEVR.
1075  */
1076  if (!rpmdsAnyMatchesDep(sourceH, trigger, 1))
1077  continue;
1078 
1079  if (!( hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
1080  &triggerIndices, NULL) &&
1081  hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
1082  &triggerScripts, NULL) &&
1083  hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
1084  &triggerProgs, NULL))
1085  )
1086  continue;
1087 
1088  { int arg1;
1089  int index;
1090 
1091  arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
1092  if (arg1 < 0) {
1093  /* XXX W2DO? fails as "execution of script failed" */
1094  rc = RPMRC_FAIL;
1095  } else {
1096  arg1 += psm->countCorrection;
1097  index = triggerIndices[i];
1098  if (triggersAlreadyRun == NULL ||
1099  triggersAlreadyRun[index] == 0)
1100  {
1101  rc = runScript(psm, triggeredH, "%trigger", 1,
1102  triggerProgs + index, triggerScripts[index],
1103  arg1, arg2);
1104  if (triggersAlreadyRun != NULL)
1105  triggersAlreadyRun[index] = 1;
1106  }
1107  }
1108  }
1109 
1110  triggerIndices = hfd(triggerIndices, tit);
1111  triggerScripts = hfd(triggerScripts, tst);
1112  triggerProgs = hfd(triggerProgs, tpt);
1113 
1114  /*
1115  * Each target/source header pair can only result in a single
1116  * script being run.
1117  */
1118  break;
1119  }
1120 
1121  trigger = rpmdsFree(trigger);
1122 
1123  return rc;
1124 }
1125 
1132  /*@globals rpmGlobalMacroContext, h_errno,
1133  fileSystem, internalState @*/
1134  /*@modifies psm, rpmGlobalMacroContext,
1135  fileSystem, internalState @*/
1136 {
1137  const rpmts ts = psm->ts;
1138  rpmfi fi = psm->fi;
1139  int numPackage = -1;
1140  rpmRC rc = RPMRC_OK;
1141  const char * N = NULL;
1142 
1143  if (psm->te) /* XXX can't happen */
1144  N = rpmteN(psm->te);
1145 /* XXX: Might need to adjust instance counts for autorollback. */
1146  if (N) /* XXX can't happen */
1147  numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N)
1148  + psm->countCorrection;
1149  if (numPackage < 0)
1150  return RPMRC_NOTFOUND;
1151 
1152  if (fi != NULL && fi->h != NULL) /* XXX can't happen */
1153  { Header triggeredH;
1155  int countCorrection = psm->countCorrection;
1156 
1157  psm->countCorrection = 0;
1158  mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, N, 0);
1159  while((triggeredH = rpmdbNextIterator(mi)) != NULL)
1160  rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
1161  mi = rpmdbFreeIterator(mi);
1163  }
1164 
1165  return rc;
1166 }
1167 
1174  /*@globals rpmGlobalMacroContext, h_errno,
1175  fileSystem, internalState @*/
1176  /*@modifies psm, rpmGlobalMacroContext,
1177  fileSystem, internalState @*/
1178 {
1179  const rpmts ts = psm->ts;
1180  rpmfi fi = psm->fi;
1181  HGE_t hge = fi->hge;
1182  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1183  const char ** triggerNames;
1184  int numTriggers;
1185  int_32 * triggerIndices;
1186  rpmTagType tnt, tit;
1187  int numTriggerIndices;
1188  unsigned char * triggersRun;
1189  rpmRC rc = RPMRC_OK;
1190  size_t nb;
1191 
1192  if (fi->h == NULL) return rc; /* XXX can't happen */
1193 
1194  if (!( hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
1195  &triggerNames, &numTriggers) &&
1196  hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
1197  &triggerIndices, &numTriggerIndices))
1198  )
1199  return rc;
1200 
1201  nb = sizeof(*triggersRun) * numTriggerIndices;
1202  triggersRun = memset(alloca(nb), 0, nb);
1203 
1204  { Header sourceH = NULL;
1205  int i;
1206 
1207  for (i = 0; i < numTriggers; i++) {
1209 
1210  if (triggersRun[triggerIndices[i]] != 0) continue;
1211 
1212  mi = rpmtsInitIterator(ts, RPMTAG_NAME, triggerNames[i], 0);
1213 
1214  while((sourceH = rpmdbNextIterator(mi)) != NULL) {
1215  rc |= handleOneTrigger(psm, sourceH, fi->h,
1217  triggersRun);
1218  }
1219 
1220  mi = rpmdbFreeIterator(mi);
1221  }
1222  }
1223  triggerIndices = hfd(triggerIndices, tit);
1224  triggerNames = hfd(triggerNames, tnt);
1225  return rc;
1226 }
1227 
1228 /*@observer@*/
1229 static const char * pkgStageString(pkgStage a)
1230  /*@*/
1231 {
1232  switch(a) {
1233  case PSM_UNKNOWN: return "unknown";
1234 
1235  case PSM_PKGINSTALL: return " install";
1236  case PSM_PKGERASE: return " erase";
1237  case PSM_PKGCOMMIT: return " commit";
1238  case PSM_PKGSAVE: return "repackage";
1239 
1240  case PSM_INIT: return "init";
1241  case PSM_PRE: return "pre";
1242  case PSM_PROCESS: return "process";
1243  case PSM_POST: return "post";
1244  case PSM_UNDO: return "undo";
1245  case PSM_FINI: return "fini";
1246 
1247  case PSM_CREATE: return "create";
1248  case PSM_NOTIFY: return "notify";
1249  case PSM_DESTROY: return "destroy";
1250  case PSM_COMMIT: return "commit";
1251 
1252  case PSM_CHROOT_IN: return "chrootin";
1253  case PSM_CHROOT_OUT: return "chrootout";
1254  case PSM_SCRIPT: return "script";
1255  case PSM_TRIGGERS: return "triggers";
1256  case PSM_IMMED_TRIGGERS: return "immedtriggers";
1257 
1258  case PSM_RPMIO_FLAGS: return "rpmioflags";
1259 
1260  case PSM_RPMDB_LOAD: return "rpmdbload";
1261  case PSM_RPMDB_ADD: return "rpmdbadd";
1262  case PSM_RPMDB_REMOVE: return "rpmdbremove";
1263 
1264  default: return "???";
1265  }
1266  /*@noteached@*/
1267 }
1268 
1269 rpmpsm XrpmpsmUnlink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1270 {
1271  if (psm == NULL) return NULL;
1272 /*@-modfilesys@*/
1273 if (_psm_debug && msg != NULL)
1274 fprintf(stderr, "--> psm %p -- %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1275 /*@=modfilesys@*/
1276  psm->nrefs--;
1277  return NULL;
1278 }
1279 
1280 rpmpsm XrpmpsmLink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1281 {
1282  if (psm == NULL) return NULL;
1283  psm->nrefs++;
1284 
1285 /*@-modfilesys@*/
1286 if (_psm_debug && msg != NULL)
1287 fprintf(stderr, "--> psm %p ++ %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1288 /*@=modfilesys@*/
1289 
1290  /*@-refcounttrans@*/ return psm; /*@=refcounttrans@*/
1291 }
1292 
1294 {
1295  const char * msg = "rpmpsmFree";
1296  if (psm == NULL)
1297  return NULL;
1298 
1299  if (psm->nrefs > 1)
1300  return rpmpsmUnlink(psm, msg);
1301 
1302 /*@-nullstate@*/
1303  psm->fi = rpmfiFree(psm->fi);
1304 #ifdef NOTYET
1305  psm->te = rpmteFree(psm->te);
1306 #else
1307  psm->te = NULL;
1308 #endif
1309 /*@-internalglobs@*/
1310  psm->ts = rpmtsFree(psm->ts);
1311 /*@=internalglobs@*/
1312 
1313  psm->sstates = _free(psm->sstates);
1314 
1315  (void) rpmpsmUnlink(psm, msg);
1316 
1317  /*@-refcounttrans -usereleased@*/
1318 /*@-boundswrite@*/
1319  memset(psm, 0, sizeof(*psm)); /* XXX trash and burn */
1320 /*@=boundswrite@*/
1321  psm = _free(psm);
1322  /*@=refcounttrans =usereleased@*/
1323 
1324  return NULL;
1325 /*@=nullstate@*/
1326 }
1327 
1329 {
1330  const char * msg = "rpmpsmNew";
1331  rpmpsm psm = xcalloc(1, sizeof(*psm));
1332 
1333  if (ts) psm->ts = rpmtsLink(ts, msg);
1334 #ifdef NOTYET
1335  if (te) psm->te = rpmteLink(te, msg);
1336 #else
1337 /*@-assignexpose -temptrans @*/
1338  if (te) psm->te = te;
1339 /*@=assignexpose =temptrans @*/
1340 #endif
1341  if (fi) psm->fi = rpmfiLink(fi, msg);
1342 
1343  psm->sstates = xcalloc(RPMSCRIPT_MAX, sizeof(*psm->sstates));
1344 
1345  return rpmpsmLink(psm, msg);
1346 }
1347 
1355  /*@*/
1356 {
1357  uint_32 val = 0;
1358  int_32 typ = 0;
1359  void * ptr = NULL;
1360  int_32 cnt = 0;
1361 
1362  if (headerGetEntry(h, tag, &typ, &ptr, &cnt)
1363  && typ == RPM_INT32_TYPE && ptr != NULL && cnt == 1)
1364  val = *(uint_32 *)ptr;
1365  ptr = headerFreeData(ptr, typ);
1366  return val;
1367 }
1368 
1376 static int hCopyTag(Header sh, Header th, int_32 tag)
1377  /*@modifies th @*/
1378 {
1379  int_32 typ = 0;
1380  void * ptr = NULL;
1381  int_32 cnt = 0;
1382  int xx = 1;
1383 
1384  if (headerGetEntry(sh, tag, &typ, &ptr, &cnt) && cnt > 0)
1385  xx = headerAddEntry(th, tag, typ, ptr, cnt);
1386 assert(xx);
1387  ptr = headerFreeData(ptr, typ);
1388  return 0;
1389 }
1390 
1397 static int hSaveBlinks(Header h, const struct rpmChainLink_s * blink)
1398  /*@modifies h @*/
1399 {
1400  /*@observer@*/
1401  static const char * chain_end = RPMTE_CHAIN_END;
1402  int ac;
1403  int xx = 1;
1404 
1405  ac = argvCount(blink->NEVRA);
1406  if (ac > 0)
1408  argvData(blink->NEVRA), ac);
1409  else /* XXX Add an explicit chain terminator on 1st install. */
1411  &chain_end, 1);
1412 assert(xx);
1413 
1414  ac = argvCount(blink->Pkgid);
1415  if (ac > 0)
1417  argvData(blink->Pkgid), ac);
1418  else /* XXX Add an explicit chain terminator on 1st install. */
1420  &chain_end, 1);
1421 assert(xx);
1422 
1423  ac = argvCount(blink->Hdrid);
1424  if (ac > 0)
1426  argvData(blink->Hdrid), ac);
1427  else /* XXX Add an explicit chain terminator on 1st install. */
1429  &chain_end, 1);
1430 assert(xx);
1431 
1432  return 0;
1433 }
1434 
1441 static int hSaveFlinks(Header h, const struct rpmChainLink_s * flink)
1442  /*@modifies h @*/
1443 {
1444 #ifdef NOTYET
1445  /*@observer@*/
1446  static const char * chain_end = RPMTE_CHAIN_END;
1447 #endif
1448  int ac;
1449  int xx = 1;
1450 
1451  /* Save backward links into header upgrade chain. */
1452  ac = argvCount(flink->NEVRA);
1453  if (ac > 0)
1455  argvData(flink->NEVRA), ac);
1456 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
1457  else /* XXX Add an explicit chain terminator on 1st install. */
1459  &chain_end, 1);
1460 #endif
1461 assert(xx);
1462 
1463  ac = argvCount(flink->Pkgid);
1464  if (ac > 0)
1466  argvData(flink->Pkgid), ac);
1467 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
1468  else /* XXX Add an explicit chain terminator on 1st install. */
1470  &chain_end, 1);
1471 #endif
1472 assert(xx);
1473 
1474  ac = argvCount(flink->Hdrid);
1475  if (ac > 0)
1477  argvData(flink->Hdrid), ac);
1478 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
1479  else /* XXX Add an explicit chain terminator on 1st install. */
1481  &chain_end, 1);
1482 #endif
1483 assert(xx);
1484 
1485  return 0;
1486 }
1487 
1495 static int populateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
1496  /*@modifies fi @*/
1497 {
1498  uint_32 tscolor = rpmtsColor(ts);
1499  uint_32 tecolor = rpmteColor(te);
1500  int_32 installTime = (int_32) time(NULL);
1501  int fc = rpmfiFC(fi);
1502  const char * origin;
1503  int xx = 1;
1504 
1505 assert(fi->h != NULL);
1506 
1508  &installTime, 1);
1509 assert(xx);
1510 
1512  &tscolor, 1);
1513 assert(xx);
1514 
1515  /* XXX FIXME: add preferred color at install. */
1516 
1518  &tecolor, 1);
1519 assert(xx);
1520 
1521  /* Add the header's origin (i.e. URL) */
1522  origin = headerGetOrigin(fi->h);
1523  if (origin != NULL)
1525  origin, 1);
1526 assert(xx);
1527 
1528  /* XXX Don't clobber forward/backward upgrade chain on rollbacks */
1529  if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
1530  xx = hSaveBlinks(fi->h, &te->blink);
1531 
1532  return 0;
1533 }
1534 
1535 
1543 static int postPopulateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
1544  /*@modifies fi @*/
1545 {
1546  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1547  int fc = rpmfiFC(fi);
1548  int xx = 1;
1549 
1550  if (fi->fstates != NULL && fc > 0) {
1551  xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE, fi->fstates, fc);
1552  }
1553 
1554  return 0;
1555 }
1556 
1557 static void * rpmpsmThread(void * arg)
1558  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1559  /*@modifies arg, rpmGlobalMacroContext, fileSystem, internalState @*/
1560 {
1561  rpmpsm psm = arg;
1562 /*@-unqualifiedtrans@*/
1563  return ((void *) rpmpsmStage(psm, psm->nstage));
1564 /*@=unqualifiedtrans@*/
1565 }
1566 
1568  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1569  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
1570 {
1571  psm->nstage = nstage;
1572  if (_psm_threads)
1573  return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
1574  return rpmpsmStage(psm, psm->nstage);
1575 }
1576 
1578 {
1579  indexEntry entry;
1580  int i;
1581 
1582  for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
1583  if (entry->info.tag == RPMTAG_PAYLOADCOMPRESSOR) {
1584  memcpy(entry->data, "gzip", 4);
1585  break;
1586  }
1587  }
1588 }
1589 
1594 /*@-bounds -nullpass@*/ /* FIX: testing null annotation for fi->h */
1596 {
1597  const rpmts ts = psm->ts;
1598  uint_32 tscolor = rpmtsColor(ts);
1599  rpmfi fi = psm->fi;
1600  HGE_t hge = fi->hge;
1601  HAE_t hae = fi->hae;
1602  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1603  rpmRC rc = psm->rc;
1604  int saveerrno;
1605  int xx;
1606 
1607 /*@-branchstate@*/
1608  switch (stage) {
1609  case PSM_UNKNOWN:
1610  break;
1611  case PSM_INIT:
1612  rpmMessage(RPMMESS_DEBUG, D_("%s: %s has %d files, test = %d\n"),
1613  psm->stepName, rpmteNEVR(psm->te),
1614  rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
1615 
1616  /*
1617  * When we run scripts, we pass an argument which is the number of
1618  * versions of this package that will be installed when we are
1619  * finished.
1620  */
1622  if (psm->npkgs_installed < 0) {
1623  rc = RPMRC_FAIL;
1624  break;
1625  }
1626 
1627  /* Adjust package count on rollback downgrade. */
1628 assert(psm->te != NULL);
1630  (psm->goal & ~(PSM_PKGSAVE|PSM_PKGERASE)))
1631  {
1632  if (psm->te->downgrade)
1633  psm->npkgs_installed--;
1634  }
1635 
1636  if (psm->goal == PSM_PKGINSTALL) {
1637  int fc = rpmfiFC(fi);
1638  const char * hdrid;
1639 
1640  /* Add per-transaction data to install header. */
1641  xx = populateInstallHeader(ts, psm->te, fi);
1642 
1643  psm->scriptArg = psm->npkgs_installed + 1;
1644 
1645 assert(psm->mi == NULL);
1646  hdrid = rpmteHdrid(psm->te);
1647  if (hdrid != NULL) {
1648  /* XXX should use RPMTAG_HDRID not RPMTAG_SHA1HEADER */
1649  psm->mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, hdrid, 0);
1650  } else {
1651  psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te),0);
1652  xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
1653  rpmteE(psm->te));
1654  xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
1655  rpmteV(psm->te));
1656  xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
1657  rpmteR(psm->te));
1658  if (tscolor) {
1659  xx = rpmdbSetIteratorRE(psm->mi,RPMTAG_ARCH, RPMMIRE_STRCMP,
1660  rpmteA(psm->te));
1661  xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_OS, RPMMIRE_STRCMP,
1662  rpmteO(psm->te));
1663  }
1664  }
1665 
1666  while ((psm->oh = rpmdbNextIterator(psm->mi)) != NULL) {
1667  fi->record = rpmdbGetIteratorOffset(psm->mi);
1668  psm->oh = NULL;
1669  /*@loopbreak@*/ break;
1670  }
1671  psm->mi = rpmdbFreeIterator(psm->mi);
1672 
1673  rc = RPMRC_OK;
1674 
1675  /* XXX lazy alloc here may need to be done elsewhere. */
1676  if (fi->fstates == NULL && fc > 0) {
1677  fi->fstates = xmalloc(sizeof(*fi->fstates) * fc);
1678  memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
1679  }
1680 
1681  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1682  if (fc <= 0) break;
1683 
1684  /*
1685  * Old format relocatable packages need the entire default
1686  * prefix stripped to form the cpio list, while all other packages
1687  * need the leading / stripped.
1688  */
1689  { const char * p;
1690  xx = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, &p, NULL);
1691  fi->striplen = (xx ? strlen(p) + 1 : 1);
1692  }
1693  fi->mapflags =
1695 
1696  if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
1697  rpmfiBuildFNames(fi->h, RPMTAG_ORIGBASENAMES, &fi->apath, NULL);
1698  else
1699  rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
1700 
1701  if (fi->fuser == NULL)
1702  xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
1703  &fi->fuser, NULL);
1704  if (fi->fgroup == NULL)
1705  xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
1706  &fi->fgroup, NULL);
1707  rc = RPMRC_OK;
1708  }
1709  if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1710  psm->scriptArg = psm->npkgs_installed - 1;
1711 
1712  /* Retrieve installed header. */
1713  rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
1714 if (rc == RPMRC_OK)
1715 if (psm->te)
1716 psm->te->h = headerLink(fi->h);
1717  }
1718  if (psm->goal == PSM_PKGSAVE) {
1719  /* Open output package for writing. */
1720  { char tiddn[32];
1721  const char * bfmt;
1722  const char * pkgdn;
1723  const char * pkgbn;
1724 
1725  xx = snprintf(tiddn, sizeof(tiddn), "%d", rpmtsGetTid(ts));
1726  bfmt = rpmGetPath(tiddn, "/", "%{_repackage_name_fmt}", NULL);
1727  pkgbn = headerSprintf(fi->h, bfmt,
1728  rpmTagTable, rpmHeaderFormats, NULL);
1729  bfmt = _free(bfmt);
1730  psm->pkgURL = rpmGenPath("%{?_repackage_root}",
1731  "%{?_repackage_dir}",
1732  pkgbn);
1733  pkgbn = _free(pkgbn);
1734  (void) urlPath(psm->pkgURL, &psm->pkgfn);
1735  pkgdn = dirname(xstrdup(psm->pkgfn));
1736  rc = rpmMkdirPath(pkgdn, "_repackage_dir");
1737  pkgdn = _free(pkgdn);
1738  if (rc == RPMRC_FAIL)
1739  break;
1740  psm->fd = Fopen(psm->pkgfn, "w");
1741  if (psm->fd == NULL || Ferror(psm->fd)) {
1742  rc = RPMRC_FAIL;
1743  break;
1744  }
1745  }
1746  }
1747  break;
1748  case PSM_PRE:
1749  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1750 
1751 /* XXX insure that trigger index is opened before entering chroot. */
1752 #ifdef NOTYET
1753  { static int oneshot = 0;
1754  dbiIndex dbi;
1755  if (!oneshot) {
1756  dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
1757  oneshot++;
1758  }
1759  }
1760 #endif
1761 
1762  /* Change root directory if requested and not already done. */
1763  rc = rpmpsmNext(psm, PSM_CHROOT_IN);
1764 
1765  if (psm->goal == PSM_PKGINSTALL) {
1766  psm->scriptTag = RPMTAG_PREIN;
1767  psm->progTag = RPMTAG_PREINPROG;
1768  psm->sense = RPMSENSE_TRIGGERPREIN;
1769  psm->countCorrection = 0; /* XXX is this correct?!? */
1770 
1772 
1773  /* Run triggers in other package(s) this package sets off. */
1774  rc = rpmpsmNext(psm, PSM_TRIGGERS);
1775  if (rc) break;
1776 
1777  /* Run triggers in this package other package(s) set off. */
1778  rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1779  if (rc) break;
1780  }
1781 
1782  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
1783  rc = rpmpsmNext(psm, PSM_SCRIPT);
1784  if (rc != RPMRC_OK) {
1786  _("%s: %s scriptlet failed (%d), skipping %s\n"),
1787  psm->stepName, tag2sln(psm->scriptTag), rc,
1788  rpmteNEVR(psm->te));
1789  break;
1790  }
1791  }
1792  }
1793 
1794  if (psm->goal == PSM_PKGERASE) {
1795  psm->scriptTag = RPMTAG_PREUN;
1796  psm->progTag = RPMTAG_PREUNPROG;
1797  psm->sense = RPMSENSE_TRIGGERUN;
1798  psm->countCorrection = -1;
1799 
1800  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
1801  /* Run triggers in this package other package(s) set off. */
1802  rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1803  if (rc) break;
1804 
1805  /* Run triggers in other package(s) this package sets off. */
1806  rc = rpmpsmNext(psm, PSM_TRIGGERS);
1807  if (rc) break;
1808  }
1809 
1810  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
1811  rc = rpmpsmNext(psm, PSM_SCRIPT);
1812  }
1813  if (psm->goal == PSM_PKGSAVE) {
1814  int noArchiveSize = 0;
1815  const char * origin;
1816 
1817  /* Regenerate original header. */
1818  { void * uh = NULL;
1819  int_32 uht, uhc;
1820 
1821  /* Save originnal header's origin (i.e. URL) */
1822  origin = NULL;
1823  xx = headerGetEntry(fi->h, RPMTAG_PACKAGEORIGIN, NULL,
1824  &origin, NULL);
1825 
1826  /* Retrieve original header blob. */
1827  if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
1828  psm->oh = headerCopyLoad(uh);
1829  uh = hfd(uh, uht);
1830  } else
1831  if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
1832  {
1833  HeaderIterator hi;
1834  int_32 tag, type, count;
1835  hPTR_t ptr;
1836  Header oh;
1837 
1838  /* Load the original header from the blob. */
1839  oh = headerCopyLoad(uh);
1840 
1841  /* XXX this is headerCopy w/o headerReload() */
1842  psm->oh = headerNew();
1843 
1844  /*@-branchstate@*/
1845  for (hi = headerInitIterator(oh);
1846  headerNextIterator(hi, &tag, &type, &ptr, &count);
1847  ptr = headerFreeData((void *)ptr, type))
1848  {
1849  if (tag == RPMTAG_ARCHIVESIZE)
1850  noArchiveSize = 1;
1851  if (ptr) xx = hae(psm->oh, tag, type, ptr, count);
1852  }
1853  hi = headerFreeIterator(hi);
1854  /*@=branchstate@*/
1855 
1856  oh = headerFree(oh);
1857  uh = hfd(uh, uht);
1858  } else
1859  break; /* XXX shouldn't ever happen */
1860  }
1861 
1862  /* Retrieve type of payload compression. */
1863  /*@-nullstate@*/ /* FIX: psm->oh may be NULL */
1864  rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1865  /*@=nullstate@*/
1866 
1867  /* Write the lead section into the package. */
1868  { struct rpmlead lead;
1869 
1870  memset(&lead, 0, sizeof(lead));
1871  /* XXX Set package version conditioned on noDirTokens. */
1872  lead.major = 3;
1873  lead.minor = 0;
1874  lead.type = RPMLEAD_BINARY;
1875 
1876  /* XXX DIEDIEDIE: legacy values were not 0. */
1877  lead.archnum = 0;
1878  lead.osnum = 0;
1880 
1881  strncpy(lead.name, rpmteNEVR(psm->te), sizeof(lead.name));
1882 
1883  rc = writeLead(psm->fd, &lead);
1884  if (rc != RPMRC_OK) {
1885  rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
1886  Fstrerror(psm->fd));
1887  break;
1888  }
1889  }
1890 
1891  /* Write the signature section into the package. */
1892  /* XXX rpm-4.1 and later has archive size in signature header. */
1893  { Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
1894  /* Reallocate the signature into one contiguous region. */
1895  sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
1896  if (sigh == NULL) {
1897  rpmError(RPMERR_NOSPACE, _("Unable to reload signature header\n"));
1898  rc = RPMRC_FAIL;
1899  break;
1900  }
1901  rc = rpmWriteSignature(psm->fd, sigh);
1902  sigh = rpmFreeSignature(sigh);
1903  if (rc) break;
1904  }
1905 
1906  /* Add remove transaction id to header. */
1907  if (psm->oh != NULL)
1908  { int_32 tid = rpmtsGetTid(ts);
1909 
1910  xx = hae(psm->oh, RPMTAG_REMOVETID, RPM_INT32_TYPE,
1911  &tid, 1);
1912 
1913  /* Add original header's origin (i.e. URL) */
1914  if (origin != NULL)
1915  xx = hae(psm->oh, RPMTAG_PACKAGEORIGIN, RPM_STRING_TYPE,
1916  origin, 1);
1917 
1918  /* Copy upgrade chain link tags. */
1919  xx = hCopyTag(fi->h, psm->oh, RPMTAG_INSTALLTID);
1920  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKPKGID);
1921  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKHDRID);
1922  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKNEVRA);
1923 
1924 assert(psm->te != NULL);
1925  xx = hSaveFlinks(psm->oh, &psm->te->flink);
1926  }
1927 
1928  /* Write the metadata section into the package. */
1929  rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
1930  if (rc) break;
1931  }
1932  break;
1933  case PSM_PROCESS:
1934  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1935 
1936  if (psm->goal == PSM_PKGINSTALL) {
1937 
1938  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1939 
1940  /* XXX Synthesize callbacks for packages with no files. */
1941  if (rpmfiFC(fi) <= 0) {
1942  void * ptr;
1943  ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_START, 0, 100);
1944  ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
1945  break;
1946  }
1947 
1948  /* Retrieve type of payload compression. */
1949  rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1950 
1951  if (rpmteFd(fi->te) == NULL) { /* XXX can't happen */
1952  rc = RPMRC_FAIL;
1953  break;
1954  }
1955 
1956  /*@-nullpass@*/ /* LCL: fi->fd != NULL here. */
1957  psm->cfd = Fdopen(fdDup(Fileno(rpmteFd(fi->te))), psm->rpmio_flags);
1958  /*@=nullpass@*/
1959  if (psm->cfd == NULL) { /* XXX can't happen */
1960  rc = RPMRC_FAIL;
1961  break;
1962  }
1963 
1964  rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, psm->payload_format, ts, fi,
1965  psm->cfd, NULL, &psm->failedFile);
1966  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
1967  fdstat_op(psm->cfd, FDSTAT_READ));
1968  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
1969  fdstat_op(psm->cfd, FDSTAT_DIGEST));
1970  xx = fsmTeardown(fi->fsm);
1971 
1972  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1973  xx = Fclose(psm->cfd);
1974  psm->cfd = NULL;
1975  /*@-mods@*/
1976  errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1977  /*@=mods@*/
1978 
1979  if (!rc)
1980  rc = rpmpsmNext(psm, PSM_COMMIT);
1981 
1982  /* XXX make sure progress is closed out */
1984  psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1985  psm->total = psm->amount;
1986  xx = rpmpsmNext(psm, PSM_NOTIFY);
1987 
1988  if (rc) {
1990  _("unpacking of archive failed%s%s: %s\n"),
1991  (psm->failedFile != NULL ? _(" on file ") : ""),
1992  (psm->failedFile != NULL ? psm->failedFile : ""),
1993  cpioStrerror(rc));
1994  rc = RPMRC_FAIL;
1995 
1996  /* XXX notify callback on error. */
1998  psm->amount = 0;
1999  psm->total = 0;
2000  xx = rpmpsmNext(psm, PSM_NOTIFY);
2001 
2002  break;
2003  }
2004  }
2005  if (psm->goal == PSM_PKGERASE) {
2006  int fc = rpmfiFC(fi);
2007 
2008  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
2009  if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
2010  if (fc <= 0) break;
2011 
2013  psm->amount = fc; /* XXX W2DO? looks wrong. */
2014  psm->total = fc;
2015  xx = rpmpsmNext(psm, PSM_NOTIFY);
2016 
2017  rc = fsmSetup(fi->fsm, FSM_PKGERASE, psm->payload_format, ts, fi,
2018  NULL, NULL, &psm->failedFile);
2019  xx = fsmTeardown(fi->fsm);
2020 
2022  psm->amount = 0; /* XXX W2DO? looks wrong. */
2023  psm->total = fc;
2024  xx = rpmpsmNext(psm, PSM_NOTIFY);
2025 
2026  }
2027  if (psm->goal == PSM_PKGSAVE) {
2028  fileAction * actions = fi->actions;
2029  fileAction action = fi->action;
2030 
2031  fi->action = FA_COPYOUT;
2032  fi->actions = NULL;
2033 
2034  if (psm->fd == NULL) { /* XXX can't happen */
2035  rc = RPMRC_FAIL;
2036  break;
2037  }
2038  /*@-nullpass@*/ /* FIX: fdDup mey return NULL. */
2039  xx = Fflush(psm->fd);
2040  psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
2041  /*@=nullpass@*/
2042  if (psm->cfd == NULL) { /* XXX can't happen */
2043  rc = RPMRC_FAIL;
2044  break;
2045  }
2046 
2047  rc = fsmSetup(fi->fsm, FSM_PKGBUILD, psm->payload_format, ts, fi,
2048  psm->cfd, NULL, &psm->failedFile);
2049  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
2050  fdstat_op(psm->cfd, FDSTAT_WRITE));
2051  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
2052  fdstat_op(psm->cfd, FDSTAT_DIGEST));
2053  xx = fsmTeardown(fi->fsm);
2054 
2055  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
2056  xx = Fclose(psm->cfd);
2057  psm->cfd = NULL;
2058  /*@-mods@*/
2059  errno = saveerrno;
2060  /*@=mods@*/
2061 
2062  /* XXX make sure progress is closed out */
2064  psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
2065  psm->total = psm->amount;
2066  xx = rpmpsmNext(psm, PSM_NOTIFY);
2067 
2068  fi->action = action;
2069  fi->actions = actions;
2070  }
2071  break;
2072  case PSM_POST:
2073  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2074 
2075  if (psm->goal == PSM_PKGINSTALL) {
2076 
2077  /*
2078  * If this header has already been installed, remove it from
2079  * the database before adding the new header.
2080  */
2081  if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
2082  rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
2083  if (rc) break;
2084  }
2085 
2086  /* Add fi->fstates to install header. */
2087  xx = postPopulateInstallHeader(ts, psm->te, fi);
2088 
2089  rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
2090  if (rc) break;
2091 
2092  psm->scriptTag = RPMTAG_POSTIN;
2093  psm->progTag = RPMTAG_POSTINPROG;
2094  psm->sense = RPMSENSE_TRIGGERIN;
2095  psm->countCorrection = 0;
2096 
2097  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
2098  rc = rpmpsmNext(psm, PSM_SCRIPT);
2099  if (rc) break;
2100  }
2101  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
2102  /* Run triggers in other package(s) this package sets off. */
2103  rc = rpmpsmNext(psm, PSM_TRIGGERS);
2104  if (rc) break;
2105 
2106  /* Run triggers in this package other package(s) set off. */
2107  rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2108  if (rc) break;
2109  }
2110 
2111  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
2112  rc = markReplacedFiles(psm);
2113 
2114  }
2115  if (psm->goal == PSM_PKGERASE) {
2116 
2117  psm->scriptTag = RPMTAG_POSTUN;
2118  psm->progTag = RPMTAG_POSTUNPROG;
2119  psm->sense = RPMSENSE_TRIGGERPOSTUN;
2120  psm->countCorrection = -1;
2121 
2122  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
2123  if (rpmpsmNext(psm, PSM_SCRIPT))
2124  rpmMessage(RPMMESS_VERBOSE, _("Ignoring failed %%postun scriptlet\n"));
2125  }
2126 
2128  /* Run triggers in other package(s) this package sets off. */
2129  rc = rpmpsmNext(psm, PSM_TRIGGERS);
2130  if (rc) break;
2131 
2132  /* Run triggers in this package other package(s) set off. */
2133  rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2134  if (rc) break;
2135  }
2136 
2137  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
2138  rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
2139  }
2140  if (psm->goal == PSM_PKGSAVE) {
2141  }
2142 
2143  /* Restore root directory if changed. */
2144  xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
2145  break;
2146  case PSM_UNDO:
2147  break;
2148  case PSM_FINI:
2149  /* Restore root directory if changed. */
2150  xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
2151 
2152  if (psm->fd != NULL) {
2153  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
2154  xx = Fclose(psm->fd);
2155  psm->fd = NULL;
2156  /*@-mods@*/
2157  errno = saveerrno;
2158  /*@=mods@*/
2159  }
2160 
2161  if (psm->goal == PSM_PKGSAVE) {
2162  if (!rc && ts && ts->notify == NULL) {
2163  rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
2164  (psm->pkgURL ? psm->pkgURL : "???"));
2165  }
2166  }
2167 
2168  if (rc) {
2169  if (psm->failedFile)
2171  _("%s failed on file %s: %s\n"),
2172  psm->stepName, psm->failedFile, cpioStrerror(rc));
2173  else
2174  rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
2175  psm->stepName, cpioStrerror(rc));
2176 
2177  /* XXX notify callback on error. */
2179  psm->amount = 0;
2180  psm->total = 0;
2181  /*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
2182  xx = rpmpsmNext(psm, PSM_NOTIFY);
2183  /*@=nullstate@*/
2184  }
2185 
2186 /*@-branchstate@*/
2187  if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
2188 if (psm->te != NULL)
2189 if (psm->te->h != NULL)
2190 psm->te->h = headerFree(psm->te->h);
2191  if (fi->h != NULL)
2192  fi->h = headerFree(fi->h);
2193  }
2194 /*@=branchstate@*/
2195  psm->oh = headerFree(psm->oh);
2196  psm->pkgURL = _free(psm->pkgURL);
2197  psm->rpmio_flags = _free(psm->rpmio_flags);
2198  psm->payload_format = _free(psm->payload_format);
2199  psm->failedFile = _free(psm->failedFile);
2200 
2201  fi->fgroup = hfd(fi->fgroup, -1);
2202  fi->fuser = hfd(fi->fuser, -1);
2203  fi->apath = _free(fi->apath);
2204  fi->fstates = _free(fi->fstates);
2205  break;
2206 
2207  case PSM_PKGINSTALL:
2208  case PSM_PKGERASE:
2209  case PSM_PKGSAVE:
2210  psm->goal = stage;
2211  psm->rc = RPMRC_OK;
2212  psm->stepName = pkgStageString(stage);
2213 
2214  rc = rpmpsmNext(psm, PSM_INIT);
2215  if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
2216  if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
2217  if (!rc) rc = rpmpsmNext(psm, PSM_POST);
2218  xx = rpmpsmNext(psm, PSM_FINI);
2219  break;
2220  case PSM_PKGCOMMIT:
2221  break;
2222 
2223  case PSM_CREATE:
2224  break;
2225  case PSM_NOTIFY:
2226  { void * ptr;
2227 /*@-nullpass@*/ /* FIX: psm->te may be NULL */
2228  ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
2229 /*@-nullpass@*/
2230  } break;
2231  case PSM_DESTROY:
2232  break;
2233  case PSM_COMMIT:
2234  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
2235  if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
2236 
2237  rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, psm->payload_format, ts, fi,
2238  NULL, NULL, &psm->failedFile);
2239  xx = fsmTeardown(fi->fsm);
2240  break;
2241 
2242  case PSM_CHROOT_IN:
2243  { const char * rootDir = rpmtsRootDir(ts);
2244  /* Change root directory if requested and not already done. */
2245  if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
2246  && !rpmtsChrootDone(ts) && !psm->chrootDone)
2247  {
2248  static int _pw_loaded = 0;
2249  static int _gr_loaded = 0;
2250 
2251  if (!_pw_loaded) {
2252  (void)getpwnam("root");
2253  endpwent();
2254  _pw_loaded++;
2255  }
2256  if (!_gr_loaded) {
2257  (void)getgrnam("root");
2258  endgrent();
2259  _gr_loaded++;
2260  }
2261 
2262  xx = Chdir("/");
2263  /*@-superuser@*/
2264  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
2265  rc = Chroot(rootDir);
2266  /*@=superuser@*/
2267  psm->chrootDone = 1;
2268  (void) rpmtsSetChrootDone(ts, 1);
2269  }
2270  } break;
2271  case PSM_CHROOT_OUT:
2272  /* Restore root directory if changed. */
2273  if (psm->chrootDone) {
2274  const char * rootDir = rpmtsRootDir(ts);
2275  const char * currDir = rpmtsCurrDir(ts);
2276  /*@-superuser@*/
2277  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
2278  rc = Chroot(".");
2279  /*@=superuser@*/
2280  psm->chrootDone = 0;
2281  (void) rpmtsSetChrootDone(ts, 0);
2282  if (currDir != NULL) /* XXX can't happen */
2283  xx = Chdir(currDir);
2284  }
2285  break;
2286  case PSM_SCRIPT: /* Run current package scriptlets. */
2287  rc = runInstScript(psm);
2288  break;
2289  case PSM_TRIGGERS:
2290  /* Run triggers in other package(s) this package sets off. */
2291  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2292  rc = runTriggers(psm);
2293  break;
2294  case PSM_IMMED_TRIGGERS:
2295  /* Run triggers in this package other package(s) set off. */
2296  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2297  rc = runImmedTriggers(psm);
2298  break;
2299 
2300  case PSM_RPMIO_FLAGS:
2301  { const char * payload_compressor = NULL;
2302  const char * payload_format = NULL;
2303  char * t;
2304 
2305  /*@-branchstate@*/
2306  if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
2307  &payload_compressor, NULL))
2308  payload_compressor = "gzip";
2309  /*@=branchstate@*/
2310  psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
2311  if (psm->goal == PSM_PKGSAVE && !strcmp(payload_compressor, "lzma") && access("/usr/bin/lzma", X_OK)) {
2312  /* FIXME: digest is bad. */
2313  payload_compressor = "gzip";
2314  replace_lzma_with_gzip(psm->oh);
2315  }
2316  *t = '\0';
2317  if (!strcmp(payload_compressor, "lzma")) {
2318  t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w7" : "r"));
2319  t = stpcpy(t, ".lzdio");
2320  } else {
2321  t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
2322  if (!strcmp(payload_compressor, "gzip"))
2323  t = stpcpy(t, ".gzdio");
2324  if (!strcmp(payload_compressor, "bzip2"))
2325  t = stpcpy(t, ".bzdio");
2326  }
2327 
2328  /*@-branchstate@*/
2329  if (!hge(fi->h, RPMTAG_PAYLOADFORMAT, NULL,
2330  &payload_format, NULL)
2331  || !(!strcmp(payload_format, "tar") || !strcmp(payload_format, "ustar")))
2332  payload_format = "cpio";
2333  /*@=branchstate@*/
2334  psm->payload_format = xstrdup(payload_format);
2335  rc = RPMRC_OK;
2336  } break;
2337 
2338  case PSM_RPMDB_LOAD:
2339 assert(psm->mi == NULL);
2341  &fi->record, sizeof(fi->record));
2342  fi->h = rpmdbNextIterator(psm->mi);
2343  if (fi->h != NULL)
2344  fi->h = headerLink(fi->h);
2345  psm->mi = rpmdbFreeIterator(psm->mi);
2346 
2347  if (fi->h != NULL) {
2348  (void) headerSetInstance(fi->h, fi->record);
2349  rc = RPMRC_OK;
2350  } else
2351  rc = RPMRC_FAIL;
2352  break;
2353  case PSM_RPMDB_ADD:
2354  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2355  if (fi->h == NULL) break; /* XXX can't happen */
2356 
2357  /* Add header to db, doing header check if requested */
2358  /* XXX rollback headers propagate the previous transaction id. */
2359  { uint_32 tid = ((rpmtsType(ts) == RPMTRANS_TYPE_ROLLBACK)
2360  ? hLoadTID(fi->h, RPMTAG_INSTALLTID) : rpmtsGetTid(ts));
2361  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
2362  if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
2363  rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, ts, headerCheck);
2364  else
2365  rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, NULL, NULL);
2366  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
2367  }
2368 
2369  if (rc != RPMRC_OK) break;
2370 
2371 assert(psm->te != NULL);
2372  /* Mark non-rollback elements as installed. */
2373  if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
2374  psm->te->installed = 1;
2375 
2376  /* Set the database instance for (possible) rollbacks. */
2377  rpmteSetDBInstance(psm->te, headerGetInstance(fi->h));
2378 
2379  break;
2380  case PSM_RPMDB_REMOVE:
2381  {
2382  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2383 
2384  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
2385  rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record,
2386  NULL, NULL);
2387  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
2388 
2389  if (rc != RPMRC_OK) break;
2390 
2391  /* Forget the offset of a successfully removed header. */
2392  psm->te->u.removed.dboffset = 0;
2393 
2394  } break;
2395 
2396  default:
2397  break;
2398 /*@i@*/ }
2399 /*@=branchstate@*/
2400 
2401 /*@-nullstate@*/ /* FIX: psm->oh and psm->fi->h may be NULL. */
2402  return rc;
2403 /*@=nullstate@*/
2404 }
2405 /*@=bounds =nullpass@*/