rpm  4.5
fsm.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h>
9 #include <rpmlib.h>
10 
11 #include "cpio.h"
12 #include "tar.h"
13 
14 #include "fsm.h"
15 #define fsmUNSAFE fsmStage
16 
17 #include "rpmerr.h"
18 
19 #define _RPMFI_INTERNAL
20 #include "rpmfi.h"
21 #include "rpmte.h"
22 #include "rpmts.h"
23 #include "rpmsq.h"
24 
25 #include "ugid.h" /* XXX unameToUid() and gnameToGid() */
26 
27 #include "debug.h"
28 
29 /*@access FD_t @*/ /* XXX void ptr args */
30 /*@access FSMI_t @*/
31 /*@access FSM_t @*/
32 
33 /*@access rpmfi @*/
34 
35 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
36 
37 #define _FSM_DEBUG 0
38 /*@unchecked@*/
40 
41 /*@-exportheadervar@*/
42 /*@unchecked@*/
43 int _fsm_threads = 0;
44 /*@=exportheadervar@*/
45 
46 /* XXX Failure to remove is not (yet) cause for failure. */
47 /*@-exportlocal -exportheadervar@*/
48 /*@unchecked@*/
50 /*@=exportlocal =exportheadervar@*/
51 
52 rpmts fsmGetTs(const FSM_t fsm) {
53  const FSMI_t iter = fsm->iter;
54  /*@-compdef -refcounttrans -retexpose -usereleased @*/
55  return (iter ? iter->ts : NULL);
56  /*@=compdef =refcounttrans =retexpose =usereleased @*/
57 }
58 
59 rpmfi fsmGetFi(const FSM_t fsm)
60 {
61  const FSMI_t iter = fsm->iter;
62  /*@-compdef -refcounttrans -retexpose -usereleased @*/
63  return (iter ? iter->fi : NULL);
64  /*@=compdef =refcounttrans =retexpose =usereleased @*/
65 }
66 
67 #define SUFFIX_RPMORIG ".rpmorig"
68 #define SUFFIX_RPMSAVE ".rpmsave"
69 #define SUFFIX_RPMNEW ".rpmnew"
70 
79 static /*@only@*//*@null@*/
80 const char * fsmFsPath(/*@special@*/ /*@null@*/ const FSM_t fsm,
81  /*@null@*/ const struct stat * st,
82  /*@null@*/ const char * subdir,
83  /*@null@*/ const char * suffix)
84  /*@uses fsm->dirName, fsm->baseName */
85  /*@*/
86 {
87  const char * s = NULL;
88 
89  if (fsm) {
90  char * t;
91  int nb;
92  nb = strlen(fsm->dirName) +
93  (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) +
94  (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) +
95  strlen(fsm->baseName) + 1;
96 /*@-boundswrite@*/
97  s = t = xmalloc(nb);
98  t = stpcpy(t, fsm->dirName);
99  if (st && !S_ISDIR(st->st_mode))
100  if (subdir) t = stpcpy(t, subdir);
101  t = stpcpy(t, fsm->baseName);
102  if (st && !S_ISDIR(st->st_mode))
103  if (suffix) t = stpcpy(t, suffix);
104 /*@=boundswrite@*/
105  }
106  return s;
107 }
108 
114 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * p)
115  /*@globals fileSystem @*/
116  /*@modifies fileSystem @*/
117 {
118  FSMI_t iter = p;
119  if (iter) {
120 /*@-internalglobs@*/ /* XXX rpmswExit() */
121  iter->ts = rpmtsFree(iter->ts);
122 /*@=internalglobs@*/
123  iter->fi = rpmfiUnlink(iter->fi, "mapIterator");
124  }
125  return _free(p);
126 }
127 
134 static void *
136  /*@modifies ts, fi @*/
137 {
138  FSMI_t iter = NULL;
139 
140  iter = xcalloc(1, sizeof(*iter));
141  iter->ts = rpmtsLink(ts, "mapIterator");
142  iter->fi = rpmfiLink(fi, "mapIterator");
143  iter->reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT);
144  iter->i = (iter->reverse ? (fi->fc - 1) : 0);
145  iter->isave = iter->i;
146  return iter;
147 }
148 
154 static int mapNextIterator(/*@null@*/ void * a)
155  /*@*/
156 {
157  FSMI_t iter = a;
158  int i = -1;
159 
160  if (iter) {
161  const rpmfi fi = iter->fi;
162  if (iter->reverse) {
163  if (iter->i >= 0) i = iter->i--;
164  } else {
165  if (iter->i < fi->fc) i = iter->i++;
166  }
167  iter->isave = i;
168  }
169  return i;
170 }
171 
174 /*@-boundsread@*/
175 static int cpioStrCmp(const void * a, const void * b)
176  /*@*/
177 {
178  const char * aurl = *(const char **)a;
179  const char * burl = *(const char **)b;
180  const char * afn = NULL;
181  const char * bfn = NULL;
182 
183  (void) urlPath(aurl, &afn);
184  (void) urlPath(burl, &bfn);
185 
186  /* XXX Some 4+ year old rpm packages have basename only in payloads. */
187 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES
188  if (strchr(afn, '/') == NULL)
189  bfn = strrchr(bfn, '/') + 1;
190 #endif
191 
192  /* Match rpm-4.0 payloads with ./ prefixes. */
193  if (afn[0] == '.' && afn[1] == '/') afn += 2;
194  if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
195 
196  /* If either path is absolute, make it relative. */
197  if (afn[0] == '/') afn += 1;
198  if (bfn[0] == '/') bfn += 1;
199 
200  return strcmp(afn, bfn);
201 }
202 /*@=boundsread@*/
203 
210 /*@-boundsread@*/
211 static int mapFind(/*@null@*/ FSMI_t iter, const char * fsmPath)
212  /*@modifies iter @*/
213 {
214  int ix = -1;
215 
216  if (iter) {
217  const rpmfi fi = iter->fi;
218  if (fi && fi->fc > 0 && fi->apath && fsmPath && *fsmPath) {
219  const char ** p = NULL;
220 
221 /*@-boundswrite@*/
222  if (fi->apath != NULL)
223  p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath),
224  cpioStrCmp);
225 /*@=boundswrite@*/
226  if (p) {
227  iter->i = p - fi->apath;
228  ix = mapNextIterator(iter);
229  }
230  }
231  }
232  return ix;
233 }
234 /*@=boundsread@*/
235 
239 typedef struct dnli_s {
241 /*@only@*/ /*@null@*/
242  char * active;
243  int reverse;
244  int isave;
245  int i;
246 } * DNLI_t;
247 
253 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * a)
254  /*@modifies a @*/
255 {
256  if (a) {
257  DNLI_t dnli = (void *)a;
258  if (dnli->active) free(dnli->active);
259  }
260  return _free(a);
261 }
262 
265 static inline int dnlCount(/*@null@*/ const DNLI_t dnli)
266  /*@*/
267 {
268  return (dnli ? dnli->fi->dc : 0);
269 }
270 
273 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli)
274  /*@*/
275 {
276  return (dnli ? dnli->isave : -1);
277 }
278 
285 /*@-boundsread@*/
286 /*@-usereleased@*/
287 static /*@only@*/ /*@null@*/
288 void * dnlInitIterator(/*@special@*/ const FSM_t fsm,
289  int reverse)
290  /*@uses fsm->iter @*/
291  /*@*/
292 {
293  rpmfi fi = fsmGetFi(fsm);
294  const char * dnl;
295  DNLI_t dnli;
296  int i, j;
297 
298  if (fi == NULL)
299  return NULL;
300  dnli = xcalloc(1, sizeof(*dnli));
301  dnli->fi = fi;
302  dnli->reverse = reverse;
303  /*@-branchstate@*/
304  dnli->i = (reverse ? fi->dc : 0);
305  /*@=branchstate@*/
306 
307  if (fi->dc) {
308  dnli->active = xcalloc(fi->dc, sizeof(*dnli->active));
309 
310  /* Identify parent directories not skipped. */
311 /*@-boundswrite@*/
312  for (i = 0; i < fi->fc; i++)
313  if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1;
314 /*@=boundswrite@*/
315 
316  /* Exclude parent directories that are explicitly included. */
317  for (i = 0; i < fi->fc; i++) {
318  int dil, dnlen, bnlen;
319 
320  if (!S_ISDIR(fi->fmodes[i]))
321  continue;
322 
323  dil = fi->dil[i];
324  dnlen = strlen(fi->dnl[dil]);
325  bnlen = strlen(fi->bnl[i]);
326 
327  for (j = 0; j < fi->dc; j++) {
328  int jlen;
329 
330  if (!dnli->active[j] || j == dil)
331  /*@innercontinue@*/ continue;
332  (void) urlPath(fi->dnl[j], &dnl);
333  jlen = strlen(dnl);
334  if (jlen != (dnlen+bnlen+1))
335  /*@innercontinue@*/ continue;
336  if (strncmp(dnl, fi->dnl[dil], dnlen))
337  /*@innercontinue@*/ continue;
338  if (strncmp(dnl+dnlen, fi->bnl[i], bnlen))
339  /*@innercontinue@*/ continue;
340  if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
341  /*@innercontinue@*/ continue;
342  /* This directory is included in the package. */
343 /*@-boundswrite@*/
344  dnli->active[j] = 0;
345 /*@=boundswrite@*/
346  /*@innerbreak@*/ break;
347  }
348  }
349 
350  /* Print only once per package. */
351  if (!reverse) {
352  j = 0;
353  for (i = 0; i < fi->dc; i++) {
354  if (!dnli->active[i]) continue;
355  if (j == 0) {
356  j = 1;
358  D_("========== Directories not explicitly included in package:\n"));
359  }
360  (void) urlPath(fi->dnl[i], &dnl);
361  rpmMessage(RPMMESS_DEBUG, "%10d %s\n", i, dnl);
362  }
363  if (j)
364  rpmMessage(RPMMESS_DEBUG, "==========\n");
365  }
366  }
367  return dnli;
368 }
369 /*@=usereleased@*/
370 /*@=boundsread@*/
371 
377 /*@-boundsread@*/
378 static /*@observer@*/ /*@null@*/
379 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli)
380  /*@modifies dnli @*/
381 {
382  const char * dn = NULL;
383 
384  if (dnli) {
385  rpmfi fi = dnli->fi;
386  int i = -1;
387 
388  if (dnli->active)
389  do {
390  i = (!dnli->reverse ? dnli->i++ : --dnli->i);
391  } while (i >= 0 && i < fi->dc && !dnli->active[i]);
392 
393  if (i >= 0 && i < fi->dc)
394  dn = fi->dnl[i];
395  else
396  i = -1;
397  dnli->isave = i;
398  }
399  return dn;
400 }
401 /*@=boundsread@*/
402 
403 static void * fsmThread(void * arg)
404  /*@globals h_errno, fileSystem, internalState @*/
405  /*@modifies arg, fileSystem, internalState @*/
406 {
407  FSM_t fsm = arg;
408 /*@-unqualifiedtrans@*/
409  return ((void *) ((long)fsmStage(fsm, fsm->nstage)));
410 /*@=unqualifiedtrans@*/
411 }
412 
413 int fsmNext(FSM_t fsm, fileStage nstage)
414  /*@globals h_errno, fileSystem, internalState @*/
415  /*@modifies fsm, fileSystem, internalState @*/
416 {
417  fsm->nstage = nstage;
418  if (_fsm_threads)
419  return rpmsqJoin( rpmsqThread(fsmThread, fsm) );
420  return fsmStage(fsm, fsm->nstage);
421 }
422 
428 /*@-boundsread@*/
429 static int saveHardLink(/*@special@*/ /*@partial@*/ FSM_t fsm)
430  /*@uses fsm->links, fsm->ix, fsm->sb, fsm->goal, fsm->nsuffix @*/
431  /*@defines fsm->li @*/
432  /*@releases fsm->path @*/
433  /*@globals h_errno, fileSystem, internalState @*/
434  /*@modifies fsm, fileSystem, internalState @*/
435 {
436  struct stat * st = &fsm->sb;
437  int rc = 0;
438  int ix = -1;
439  int j;
440 
441  /* Find hard link set. */
442  /*@-branchstate@*/
443  for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
444  if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
445  break;
446  }
447  /*@=branchstate@*/
448 
449  /* New hard link encountered, add new link to set. */
450 /*@-boundswrite@*/
451  /*@-branchstate@*/
452  if (fsm->li == NULL) {
453  fsm->li = xcalloc(1, sizeof(*fsm->li));
454  fsm->li->next = NULL;
455  fsm->li->sb = *st; /* structure assignment */
456  fsm->li->nlink = st->st_nlink;
457  fsm->li->linkIndex = fsm->ix;
458  fsm->li->createdPath = -1;
459 
460  fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0]));
461  memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0])));
462  fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix));
463 
464  if (fsm->goal == FSM_PKGBUILD)
465  fsm->li->linksLeft = st->st_nlink;
466  if (fsm->goal == FSM_PKGINSTALL)
467  fsm->li->linksLeft = 0;
468 
469  /*@-kepttrans@*/
470  fsm->li->next = fsm->links;
471  /*@=kepttrans@*/
472  fsm->links = fsm->li;
473  }
474  /*@=branchstate@*/
475 /*@=boundswrite@*/
476 
477  if (fsm->goal == FSM_PKGBUILD) --fsm->li->linksLeft;
478 /*@-boundswrite@*/
479  fsm->li->filex[fsm->li->linksLeft] = fsm->ix;
480  /*@-observertrans -dependenttrans@*/
481  fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix;
482  /*@=observertrans =dependenttrans@*/
483 /*@=boundswrite@*/
484  if (fsm->goal == FSM_PKGINSTALL) fsm->li->linksLeft++;
485 
486  if (fsm->goal == FSM_PKGBUILD)
487  return (fsm->li->linksLeft > 0);
488 
489  if (fsm->goal != FSM_PKGINSTALL)
490  return 0;
491 
492  if (!(st->st_size || fsm->li->linksLeft == st->st_nlink))
493  return 1;
494 
495  /* Here come the bits, time to choose a non-skipped file name. */
496  { rpmfi fi = fsmGetFi(fsm);
497 
498  for (j = fsm->li->linksLeft - 1; j >= 0; j--) {
499  ix = fsm->li->filex[j];
500  if (ix < 0 || XFA_SKIPPING(fi->actions[ix]))
501  continue;
502  break;
503  }
504  }
505 
506  /* Are all links skipped or not encountered yet? */
507  if (ix < 0 || j < 0)
508  return 1; /* XXX W2DO? */
509 
510  /* Save the non-skipped file name and map index. */
511  fsm->li->linkIndex = j;
512  fsm->path = _free(fsm->path);
513  fsm->ix = ix;
514  rc = fsmNext(fsm, FSM_MAP);
515  return rc;
516 }
517 /*@=boundsread@*/
518 
524 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li)
525  /*@modifies li @*/
526 {
527  if (li) {
528  li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */
529  li->filex = _free(li->filex);
530  }
531  return _free(li);
532 }
533 
535 {
536  FSM_t fsm = xcalloc(1, sizeof(*fsm));
537  return fsm;
538 }
539 
541 {
542  if (fsm) {
543  fsm->path = _free(fsm->path);
544  /*@-branchstate@*/
545  while ((fsm->li = fsm->links) != NULL) {
546  fsm->links = fsm->li->next;
547  fsm->li->next = NULL;
548  fsm->li = freeHardLink(fsm->li);
549  }
550  /*@=branchstate@*/
551  fsm->dnlx = _free(fsm->dnlx);
552  fsm->ldn = _free(fsm->ldn);
553  fsm->iter = mapFreeIterator(fsm->iter);
554  }
555  return _free(fsm);
556 }
557 
558 int fsmSetup(FSM_t fsm, fileStage goal, const char * afmt,
559  const rpmts ts, const rpmfi fi, FD_t cfd,
560  unsigned int * archiveSize, const char ** failedFile)
561 {
562  size_t pos = 0;
563  int rc, ec = 0;
564 
565 /*@+voidabstract -nullpass@*/
566 if (_fsm_debug < 0)
567 fprintf(stderr, "--> %s(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", __FUNCTION__, fsm, goal, afmt, (void *)ts, fi, cfd, archiveSize, failedFile);
568 /*@=voidabstract =nullpass@*/
569 
570  if (fsm->headerRead == NULL) {
571  if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) {
572 if (_fsm_debug < 0)
573 fprintf(stderr, "\ttar vectors set\n");
574  fsm->headerRead = &tarHeaderRead;
575  fsm->headerWrite = &tarHeaderWrite;
577  fsm->blksize = TAR_BLOCK_SIZE;
578  } else {
579 if (_fsm_debug < 0)
580 fprintf(stderr, "\tcpio vectors set\n");
581  fsm->headerRead = &cpioHeaderRead;
584  fsm->blksize = 4;
585  }
586  }
587 
588  fsm->goal = goal;
589  if (cfd != NULL) {
590  fsm->cfd = fdLink(cfd, "persist (fsm)");
591  pos = fdGetCpioPos(fsm->cfd);
592  fdSetCpioPos(fsm->cfd, 0);
593  }
594  fsm->iter = mapInitIterator(ts, fi);
595 
596  if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
597  void * ptr;
598  fi->archivePos = 0;
599  ptr = rpmtsNotify(ts, fi->te,
600  RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize);
601  }
602 
603 /*@-boundswrite@*/
604  /*@-assignexpose@*/
605  fsm->archiveSize = archiveSize;
606  if (fsm->archiveSize)
607  *fsm->archiveSize = 0;
608  fsm->failedFile = failedFile;
609  if (fsm->failedFile)
610  *fsm->failedFile = NULL;
611  /*@=assignexpose@*/
612 /*@=boundswrite@*/
613 
614  memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf));
615  if (fsm->goal == FSM_PKGINSTALL) {
616  if (ts && rpmtsGetTid(ts) != -1)
617  sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts));
618  }
619 
620  ec = fsm->rc = 0;
621  rc = fsmUNSAFE(fsm, FSM_CREATE);
622  if (rc && !ec) ec = rc;
623 
624  rc = fsmUNSAFE(fsm, fsm->goal);
625  if (rc && !ec) ec = rc;
626 
627 /*@-boundswrite@*/
628  if (fsm->archiveSize && ec == 0)
629  *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos);
630 /*@=boundswrite@*/
631 
632 /*@-nullstate@*/ /* FIX: *fsm->failedFile may be NULL */
633  return ec;
634 /*@=nullstate@*/
635 }
636 
638 {
639  int rc = fsm->rc;
640 
641 if (_fsm_debug < 0)
642 fprintf(stderr, "--> %s(%p)\n", __FUNCTION__, fsm);
643  if (!rc)
644  rc = fsmUNSAFE(fsm, FSM_DESTROY);
645 
646  fsm->iter = mapFreeIterator(fsm->iter);
647  if (fsm->cfd != NULL) {
648  fsm->cfd = fdFree(fsm->cfd, "persist (fsm)");
649  fsm->cfd = NULL;
650  }
651  fsm->failedFile = NULL;
652  return rc;
653 }
654 
655 static int fsmMapFContext(FSM_t fsm)
656  /*@modifies fsm @*/
657 {
658  rpmts ts = fsmGetTs(fsm);
659  rpmfi fi = fsmGetFi(fsm);
660  struct stat * st = &fsm->sb;
661 
662  /*
663  * Find file security context (if not disabled).
664  */
665  fsm->fcontext = NULL;
666  if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 &&
668  {
669  security_context_t scon = NULL;
670 
671  if (matchpathcon(fsm->path, st->st_mode, &scon) == 0 && scon != NULL)
672  fsm->fcontext = scon;
673  else {
674  int i = fsm->ix;
675 
676  /* Get file security context from package. */
677  if (fi && i >= 0 && i < fi->fc)
678  fsm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL);
679  }
680  }
681  return 0;
682 }
683 
685 {
686  rpmfi fi = fsmGetFi(fsm); /* XXX const except for fstates */
687  int rc = 0;
688  int i;
689 
690  fsm->osuffix = NULL;
691  fsm->nsuffix = NULL;
692  fsm->astriplen = 0;
693  fsm->action = FA_UNKNOWN;
694  fsm->mapFlags = fi->mapflags;
695 
696  i = fsm->ix;
697  if (fi && i >= 0 && i < fi->fc) {
698 
699 /*@-boundsread@*/
700  fsm->astriplen = fi->astriplen;
701  fsm->action = (fi->actions ? fi->actions[i] : fi->action);
702  fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags);
703  fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
704 
705  /* src rpms have simple base name in payload. */
706  fsm->dirName = fi->dnl[fi->dil[i]];
707  fsm->baseName = fi->bnl[i];
708 /*@=boundsread@*/
709 
710 /*@-boundswrite@*/
711  switch (fsm->action) {
712  case FA_SKIP:
713  break;
714  case FA_UNKNOWN:
715  break;
716 
717  case FA_COPYOUT:
718  break;
719  case FA_COPYIN:
720  case FA_CREATE:
721 assert(rpmteType(fi->te) == TR_ADDED);
722  break;
723 
724  case FA_SKIPNSTATE:
725  if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
726  fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED;
727  break;
728 
729  case FA_SKIPNETSHARED:
730  if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
731  fi->fstates[i] = RPMFILE_STATE_NETSHARED;
732  break;
733 
734  case FA_SKIPCOLOR:
735  if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
736  fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR;
737  break;
738 
739  case FA_BACKUP:
740  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
741  switch (rpmteType(fi->te)) {
742  case TR_ADDED:
743  fsm->osuffix = SUFFIX_RPMORIG;
744  /*@innerbreak@*/ break;
745  case TR_REMOVED:
746  fsm->osuffix = SUFFIX_RPMSAVE;
747  /*@innerbreak@*/ break;
748  }
749  break;
750 
751  case FA_ALTNAME:
752 assert(rpmteType(fi->te) == TR_ADDED);
753  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
754  fsm->nsuffix = SUFFIX_RPMNEW;
755  break;
756 
757  case FA_SAVE:
758 assert(rpmteType(fi->te) == TR_ADDED);
759  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
760  fsm->osuffix = SUFFIX_RPMSAVE;
761  break;
762  case FA_ERASE:
763 #if 0 /* XXX is this a genhdlist fix? */
764  assert(rpmteType(fi->te) == TR_REMOVED);
765 #endif
766  /*
767  * XXX TODO: %ghost probably shouldn't be removed, but that changes
768  * legacy rpm behavior.
769  */
770  break;
771  default:
772  break;
773  }
774 /*@=boundswrite@*/
775 
776  if ((fsm->mapFlags & CPIO_MAP_PATH) || fsm->nsuffix) {
777  const struct stat * st = &fsm->sb;
778  fsm->path = _free(fsm->path);
779  fsm->path = fsmFsPath(fsm, st, fsm->subdir,
780  (fsm->suffix ? fsm->suffix : fsm->nsuffix));
781  }
782  }
783  return rc;
784 }
785 
787 {
788  struct stat * st = &fsm->sb;
789  rpmfi fi = fsmGetFi(fsm);
790  int i = fsm->ix;
791 
792  if (fi && i >= 0 && i < fi->fc) {
793  mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
794  mode_t finalMode = (fi->fmodes ? fi->fmodes[i] : perms);
795  dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0);
796  int_32 finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
797  uid_t uid = fi->uid;
798  gid_t gid = fi->gid;
799 
800  if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
801  if (fsm->goal == FSM_PKGINSTALL)
803  _("user %s does not exist - using root\n"), fi->fuser[i]);
804  uid = 0;
805  finalMode &= ~S_ISUID; /* turn off suid bit */
806  }
807 
808  if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
809  if (fsm->goal == FSM_PKGINSTALL)
811  _("group %s does not exist - using root\n"), fi->fgroup[i]);
812  gid = 0;
813  finalMode &= ~S_ISGID; /* turn off sgid bit */
814  }
815 
816  if (fsm->mapFlags & CPIO_MAP_MODE)
817  st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
818  if (fsm->mapFlags & CPIO_MAP_TYPE) {
819  st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
820  if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
821  && st->st_nlink == 0)
822  st->st_nlink = 1;
823  st->st_rdev = finalRdev;
824  st->st_mtime = finalMtime;
825  }
826  if (fsm->mapFlags & CPIO_MAP_UID)
827  st->st_uid = uid;
828  if (fsm->mapFlags & CPIO_MAP_GID)
829  st->st_gid = gid;
830 
831  { rpmts ts = fsmGetTs(fsm);
832 
833  /*
834  * Set file digest (if not disabled).
835  */
836  if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS)) {
837  fsm->fdigestalgo = fi->digestalgo;
838  fsm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL);
839  fsm->digestlen = fi->digestlen;
840  fsm->digest = (fi->digests ? (fi->digests + (fsm->digestlen * i)) : NULL);
841  } else {
842  fsm->fdigestalgo = 0;
843  fsm->fdigest = NULL;
844  fsm->digestlen = 0;
845  fsm->digest = NULL;
846  }
847  }
848 
849  }
850  return 0;
851 }
852 
858 /*@-compdef@*/
859 static int extractRegular(/*@special@*/ FSM_t fsm)
860  /*@uses fsm->fdigest, fsm->digest, fsm->sb, fsm->wfd @*/
861  /*@globals h_errno, fileSystem, internalState @*/
862  /*@modifies fsm, fileSystem, internalState @*/
863 {
864  const struct stat * st = &fsm->sb;
865  int left = st->st_size;
866  int rc = 0;
867 
868  rc = fsmNext(fsm, FSM_WOPEN);
869  if (rc)
870  goto exit;
871 
872  if (st->st_size > 0 && (fsm->fdigest != NULL || fsm->digest != NULL))
873  fdInitDigest(fsm->wfd, fsm->fdigestalgo, 0);
874 
875  while (left) {
876 
877  fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
878  rc = fsmNext(fsm, FSM_DREAD);
879  if (rc)
880  goto exit;
881 
882  rc = fsmNext(fsm, FSM_WRITE);
883  if (rc)
884  goto exit;
885 
886  left -= fsm->wrnb;
887 
888  /* Notify iff progress, completion is done elsewhere */
889  if (!rc && left)
890  (void) fsmNext(fsm, FSM_NOTIFY);
891  }
892 
893  if (st->st_size > 0 && (fsm->fdigest || fsm->digest)) {
894  void * digest = NULL;
895  int asAscii = (fsm->digest == NULL ? 1 : 0);
896 
897  (void) Fflush(fsm->wfd);
898  fdFiniDigest(fsm->wfd, fsm->fdigestalgo, &digest, NULL, asAscii);
899 
900  if (digest == NULL) {
902  goto exit;
903  }
904 
905  if (fsm->digest != NULL) {
906  if (memcmp(digest, fsm->digest, fsm->digestlen))
908  } else {
909  if (strcmp(digest, fsm->fdigest))
911  }
912  digest = _free(digest);
913  }
914 
915 exit:
916  (void) fsmNext(fsm, FSM_WCLOSE);
917  return rc;
918 }
919 /*@=compdef@*/
920 
927 /*@-compdef -compmempass@*/
928 static int writeFile(/*@special@*/ /*@partial@*/ FSM_t fsm, int writeData)
929  /*@uses fsm->path, fsm->opath, fsm->sb, fsm->osb, fsm->cfd @*/
930  /*@globals h_errno, fileSystem, internalState @*/
931  /*@modifies fsm, fileSystem, internalState @*/
932 {
933  const char * path = fsm->path;
934  const char * opath = fsm->opath;
935  struct stat * st = &fsm->sb;
936  struct stat * ost = &fsm->osb;
937  size_t left;
938  int xx;
939  int rc;
940 
941  st->st_size = (writeData ? ost->st_size : 0);
942 
943  /*@-branchstate@*/
944  if (S_ISDIR(st->st_mode)) {
945  st->st_size = 0;
946  } else if (S_ISLNK(st->st_mode)) {
947  /*
948  * While linux puts the size of a symlink in the st_size field,
949  * I don't think that's a specified standard.
950  */
951  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
952  rc = fsmUNSAFE(fsm, FSM_READLINK);
953  if (rc) goto exit;
954  st->st_size = fsm->rdnb;
955  fsm->lpath = xstrdup(fsm->rdbuf); /* XXX save readlink return. */
956  }
957  /*@=branchstate@*/
958 
959  if (fsm->mapFlags & CPIO_MAP_ABSOLUTE) {
960 /*@-boundswrite@*/
961  int nb = strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof(".");
962  char * t = alloca(nb);
963  *t = '\0';
964  fsm->path = t;
965  if (fsm->mapFlags & CPIO_MAP_ADDDOT)
966  *t++ = '.';
967  t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName);
968 /*@=boundswrite@*/
969  } else if (fsm->mapFlags & CPIO_MAP_PATH) {
970  rpmfi fi = fsmGetFi(fsm);
971  if (fi->apath) {
972  const char * apath = NULL;
973  (void) urlPath(fi->apath[fsm->ix], &apath);
974  fsm->path = apath + fi->striplen;
975  } else
976  fsm->path = fi->bnl[fsm->ix];
977  }
978 
979  rc = fsmNext(fsm, FSM_HWRITE);
980  fsm->path = path;
981  if (rc) goto exit;
982 
983  if (writeData && S_ISREG(st->st_mode)) {
984 #if HAVE_MMAP
985  char * rdbuf = NULL;
986  void * mapped = (void *)-1;
987  size_t nmapped = 0;
988  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */
989  int use_mmap = (st->st_size <= 0x07ffffff);
990 #endif
991 
992  rc = fsmNext(fsm, FSM_ROPEN);
993  if (rc) goto exit;
994 
995  /* XXX unbuffered mmap generates *lots* of fdio debugging */
996 #if HAVE_MMAP
997  if (use_mmap) {
998  mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0);
999  if (mapped != (void *)-1) {
1000  rdbuf = fsm->rdbuf;
1001  fsm->rdbuf = (char *) mapped;
1002  fsm->rdlen = nmapped = st->st_size;
1003 #if defined(MADV_DONTNEED)
1004  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1005 #endif
1006  }
1007  }
1008 #endif
1009 
1010  left = st->st_size;
1011 
1012  while (left) {
1013 #if HAVE_MMAP
1014  if (mapped != (void *)-1) {
1015  fsm->rdnb = nmapped;
1016  } else
1017 #endif
1018  {
1019  fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
1020  rc = fsmNext(fsm, FSM_READ);
1021  if (rc) goto exit;
1022  }
1023 
1024  /* XXX DWRITE uses rdnb for I/O length. */
1025  rc = fsmNext(fsm, FSM_DWRITE);
1026  if (rc) goto exit;
1027 
1028  left -= fsm->wrnb;
1029  }
1030 
1031 #if HAVE_MMAP
1032 /*@-branchstate@*/
1033  if (mapped != (void *)-1) {
1034  xx = msync(mapped, nmapped, MS_ASYNC);
1035 #if defined(MADV_DONTNEED)
1036  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1037 #endif
1038 /*@-noeffect@*/
1039  xx = munmap(mapped, nmapped);
1040 /*@=noeffect@*/
1041  fsm->rdbuf = rdbuf;
1042  } else
1043 /*@=branchstate@*/
1044 #endif
1045  xx = fsync(Fileno(fsm->rfd));
1046  }
1047 
1048  rc = fsmNext(fsm, FSM_PAD);
1049  if (rc) goto exit;
1050 
1051  rc = 0;
1052 
1053 exit:
1054  if (fsm->rfd != NULL)
1055  (void) fsmNext(fsm, FSM_RCLOSE);
1056 /*@-dependenttrans@*/
1057  fsm->opath = opath;
1058  fsm->path = path;
1059 /*@=dependenttrans@*/
1060  return rc;
1061 }
1062 /*@=compdef =compmempass@*/
1063 
1069 static int writeLinkedFile(/*@special@*/ /*@partial@*/ FSM_t fsm)
1070  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->li, fsm->failedFile @*/
1071  /*@globals h_errno, fileSystem, internalState @*/
1072  /*@modifies fsm, fileSystem, internalState @*/
1073 {
1074  const char * path = fsm->path;
1075  const char * lpath = fsm->lpath;
1076  const char * nsuffix = fsm->nsuffix;
1077  int iterIndex = fsm->ix;
1078  int ec = 0;
1079  int rc;
1080  int i;
1081  const char * linkpath = NULL;
1082  int firstfile = 1;
1083 
1084  fsm->path = NULL;
1085  fsm->lpath = NULL;
1086  fsm->nsuffix = NULL;
1087  fsm->ix = -1;
1088 
1089 /*@-boundswrite@*/
1090 /*@-branchstate@*/
1091  for (i = fsm->li->nlink - 1; i >= 0; i--) {
1092 
1093  if (fsm->li->filex[i] < 0) continue;
1094 
1095  fsm->ix = fsm->li->filex[i];
1096 /*@-compdef@*/
1097  rc = fsmNext(fsm, FSM_MAP);
1098 /*@=compdef@*/
1099 
1100  /* XXX tar and cpio have to do things differently. */
1101  if (fsm->headerWrite == tarHeaderWrite) {
1102  if (firstfile) {
1103  const char * apath = NULL;
1104  char *t;
1105  (void) urlPath(fsm->path, &apath);
1106  /* Remove the buildroot prefix. */
1107  t = xmalloc(sizeof(".") + strlen(apath + fsm->astriplen));
1108  (void) stpcpy( stpcpy(t, "."), apath + fsm->astriplen);
1109  linkpath = t;
1110  firstfile = 0;
1111  } else
1112  fsm->lpath = linkpath;
1113 
1114  /* Write data after first link for tar. */
1115  rc = writeFile(fsm, (fsm->lpath == NULL));
1116  } else {
1117  /* Write data after last link for cpio. */
1118  rc = writeFile(fsm, (i == 0));
1119  }
1120  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1121  ec = rc;
1122  *fsm->failedFile = xstrdup(fsm->path);
1123  }
1124 
1125  fsm->path = _free(fsm->path);
1126  fsm->li->filex[i] = -1;
1127  }
1128 /*@=branchstate@*/
1129 /*@=boundswrite@*/
1130 
1131 /*@-dependenttrans@*/
1132  linkpath = _free(linkpath);
1133 /*@=dependenttrans@*/
1134  fsm->ix = iterIndex;
1135  fsm->nsuffix = nsuffix;
1136  fsm->lpath = lpath;
1137  fsm->path = path;
1138  return ec;
1139 }
1140 
1146 /*@-boundsread@*/
1147 /*@-compdef@*/
1148 static int fsmMakeLinks(/*@special@*/ /*@partial@*/ FSM_t fsm)
1149  /*@uses fsm->path, fsm->opath, fsm->nsuffix, fsm->ix, fsm->li @*/
1150  /*@globals h_errno, fileSystem, internalState @*/
1151  /*@modifies fsm, fileSystem, internalState @*/
1152 {
1153  const char * path = fsm->path;
1154  const char * opath = fsm->opath;
1155  const char * nsuffix = fsm->nsuffix;
1156  int iterIndex = fsm->ix;
1157  int ec = 0;
1158  int rc;
1159  int i;
1160 
1161  fsm->path = NULL;
1162  fsm->opath = NULL;
1163  fsm->nsuffix = NULL;
1164  fsm->ix = -1;
1165 
1166  fsm->ix = fsm->li->filex[fsm->li->createdPath];
1167  rc = fsmNext(fsm, FSM_MAP);
1168  fsm->opath = fsm->path;
1169  fsm->path = NULL;
1170  /*@-branchstate@*/
1171  for (i = 0; i < fsm->li->nlink; i++) {
1172  if (fsm->li->filex[i] < 0) continue;
1173  if (fsm->li->createdPath == i) continue;
1174 
1175  fsm->ix = fsm->li->filex[i];
1176  fsm->path = _free(fsm->path);
1177  rc = fsmNext(fsm, FSM_MAP);
1178  if (XFA_SKIPPING(fsm->action)) continue;
1179 
1180  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1181  if (!rc) continue;
1182  if (!(rc == CPIOERR_ENOENT)) break;
1183 
1184  /* XXX link(fsm->opath, fsm->path) */
1185  rc = fsmNext(fsm, FSM_LINK);
1186  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1187  ec = rc;
1188 /*@-boundswrite@*/
1189  *fsm->failedFile = xstrdup(fsm->path);
1190 /*@=boundswrite@*/
1191  }
1192 
1193  fsm->li->linksLeft--;
1194  }
1195  /*@=branchstate@*/
1196  fsm->path = _free(fsm->path);
1197  fsm->opath = _free(fsm->opath);
1198 
1199  fsm->ix = iterIndex;
1200  fsm->nsuffix = nsuffix;
1201  fsm->path = path;
1202  fsm->opath = opath;
1203  return ec;
1204 }
1205 /*@=compdef@*/
1206 /*@=boundsread@*/
1207 
1213 /*@-compdef@*/
1214 static int fsmCommitLinks(/*@special@*/ /*@partial@*/ FSM_t fsm)
1215  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->sb,
1216  fsm->li, fsm->links @*/
1217  /*@globals h_errno, fileSystem, internalState @*/
1218  /*@modifies fsm, fileSystem, internalState @*/
1219 {
1220  const char * path = fsm->path;
1221  const char * nsuffix = fsm->nsuffix;
1222  int iterIndex = fsm->ix;
1223  struct stat * st = &fsm->sb;
1224  int rc = 0;
1225  int i;
1226 
1227  fsm->path = NULL;
1228  fsm->nsuffix = NULL;
1229  fsm->ix = -1;
1230 
1231  /*@-branchstate@*/
1232  for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
1233  if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
1234  break;
1235  }
1236  /*@=branchstate@*/
1237 
1238 /*@-boundswrite@*/
1239  for (i = 0; i < fsm->li->nlink; i++) {
1240  if (fsm->li->filex[i] < 0) continue;
1241  fsm->ix = fsm->li->filex[i];
1242  rc = fsmNext(fsm, FSM_MAP);
1243  if (!XFA_SKIPPING(fsm->action))
1244  rc = fsmNext(fsm, FSM_COMMIT);
1245  fsm->path = _free(fsm->path);
1246  fsm->li->filex[i] = -1;
1247  }
1248 /*@=boundswrite@*/
1249 
1250  fsm->ix = iterIndex;
1251  fsm->nsuffix = nsuffix;
1252  fsm->path = path;
1253  return rc;
1254 }
1255 /*@=compdef@*/
1256 
1262 static int fsmRmdirs(/*@special@*/ /*@partial@*/ FSM_t fsm)
1263  /*@uses fsm->path, fsm->dnlx, fsm->ldn, fsm->rdbuf, fsm->iter @*/
1264  /*@globals h_errno, fileSystem, internalState @*/
1265  /*@modifies fsm, fileSystem, internalState @*/
1266 {
1267  const char * path = fsm->path;
1268  void * dnli = dnlInitIterator(fsm, 1);
1269  char * dn = fsm->rdbuf;
1270  int dc = dnlCount(dnli);
1271  int rc = 0;
1272 
1273  fsm->path = NULL;
1274 /*@-boundswrite@*/
1275  dn[0] = '\0';
1276  /*@-observertrans -dependenttrans@*/
1277  if (fsm->ldn != NULL && fsm->dnlx != NULL)
1278  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1279  int dnlen = strlen(fsm->path);
1280  char * te;
1281 
1282  dc = dnlIndex(dnli);
1283  if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen)
1284  continue;
1285 
1286  /* Copy to avoid const on fsm->path. */
1287  te = stpcpy(dn, fsm->path) - 1;
1288  fsm->path = dn;
1289 
1290  /* Remove generated directories. */
1291  /*@-usereleased@*/ /* LCL: te used after release? */
1292  do {
1293  if (*te == '/') {
1294  *te = '\0';
1295 /*@-compdef@*/
1296  rc = fsmNext(fsm, FSM_RMDIR);
1297 /*@=compdef@*/
1298  *te = '/';
1299  }
1300  if (rc)
1301  /*@innerbreak@*/ break;
1302  te--;
1303  } while ((te - fsm->path) > fsm->dnlx[dc]);
1304  /*@=usereleased@*/
1305  }
1306 /*@=boundswrite@*/
1307  dnli = dnlFreeIterator(dnli);
1308  /*@=observertrans =dependenttrans@*/
1309 
1310  fsm->path = path;
1311  return rc;
1312 }
1313 
1319 static int fsmMkdirs(/*@special@*/ /*@partial@*/ FSM_t fsm)
1320  /*@uses fsm->path, fsm->sb, fsm->osb, fsm->rdbuf, fsm->iter,
1321  fsm->ldn, fsm->ldnlen, fsm->ldnalloc @*/
1322  /*@defines fsm->dnlx, fsm->ldn @*/
1323  /*@globals h_errno, fileSystem, internalState @*/
1324  /*@modifies fsm, fileSystem, internalState @*/
1325 {
1326  struct stat * st = &fsm->sb;
1327  struct stat * ost = &fsm->osb;
1328  const char * path = fsm->path;
1329  mode_t st_mode = st->st_mode;
1330  void * dnli = dnlInitIterator(fsm, 0);
1331  char * dn = fsm->rdbuf;
1332  int dc = dnlCount(dnli);
1333  int rc = 0;
1334  int i;
1335 /*@-compdef@*/
1336  rpmts ts = fsmGetTs(fsm);
1337 /*@=compdef@*/
1338  rpmsx sx = NULL;
1339 
1340  /* XXX Set file contexts on non-packaged dirs iff selinux enabled. */
1341  if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 &&
1343  sx = rpmtsREContext(ts);
1344 
1345  fsm->path = NULL;
1346 
1347 /*@-boundswrite@*/
1348  dn[0] = '\0';
1349  fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL);
1350  /*@-observertrans -dependenttrans@*/
1351  if (fsm->dnlx != NULL)
1352  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1353  int dnlen = strlen(fsm->path);
1354  char * te;
1355 
1356  dc = dnlIndex(dnli);
1357  if (dc < 0) continue;
1358  fsm->dnlx[dc] = dnlen;
1359  if (dnlen <= 1)
1360  continue;
1361 
1362  /*@-compdef -nullpass@*/ /* FIX: fsm->ldn not defined ??? */
1363  if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn))
1364  continue;
1365  /*@=compdef =nullpass@*/
1366 
1367  /* Copy to avoid const on fsm->path. */
1368  (void) stpcpy(dn, fsm->path);
1369  fsm->path = dn;
1370 
1371  /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
1372  (void) urlPath(dn, (const char **)&te);
1373  for (i = 1, te++; *te != '\0'; te++, i++) {
1374  if (*te != '/')
1375  /*@innercontinue@*/ continue;
1376 
1377  *te = '\0';
1378 
1379  /* Already validated? */
1380  /*@-usedef -compdef -nullpass -nullderef@*/
1381  if (i < fsm->ldnlen &&
1382  (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') &&
1383  !strncmp(fsm->path, fsm->ldn, i))
1384  {
1385  *te = '/';
1386  /* Move pre-existing path marker forward. */
1387  fsm->dnlx[dc] = (te - dn);
1388  /*@innercontinue@*/ continue;
1389  }
1390  /*@=usedef =compdef =nullpass =nullderef@*/
1391 
1392  /* Validate next component of path. */
1393  rc = fsmUNSAFE(fsm, FSM_LSTAT);
1394  *te = '/';
1395 
1396  /* Directory already exists? */
1397  if (rc == 0 && S_ISDIR(ost->st_mode)) {
1398  /* Move pre-existing path marker forward. */
1399  fsm->dnlx[dc] = (te - dn);
1400  } else if (rc == CPIOERR_ENOENT) {
1401  rpmfi fi = fsmGetFi(fsm);
1402  *te = '\0';
1403  st->st_mode = S_IFDIR | (fi->dperms & 07777);
1404  rc = fsmNext(fsm, FSM_MKDIR);
1405  if (!rc) {
1406  /* XXX FIXME? only new dir will have context set. */
1407  /* Get file security context from patterns. */
1408  if (sx != NULL) {
1409  fsm->fcontext = rpmsxFContext(sx, fsm->path, st->st_mode);
1410  rc = fsmNext(fsm, FSM_LSETFCON);
1411  }
1412  if (fsm->fcontext == NULL)
1414  D_("%s directory created with perms %04o, no context.\n"),
1415  fsm->path, (unsigned)(st->st_mode & 07777));
1416  else
1418  D_("%s directory created with perms %04o, context %s.\n"),
1419  fsm->path, (unsigned)(st->st_mode & 07777),
1420  fsm->fcontext);
1421  fsm->fcontext = NULL;
1422  }
1423  *te = '/';
1424  }
1425  if (rc)
1426  /*@innerbreak@*/ break;
1427  }
1428  if (rc) break;
1429 
1430  /* Save last validated path. */
1431 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1432  if (fsm->ldnalloc < (dnlen + 1)) {
1433  fsm->ldnalloc = dnlen + 100;
1434  fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc);
1435  }
1436  if (fsm->ldn != NULL) { /* XXX can't happen */
1437  strcpy(fsm->ldn, fsm->path);
1438  fsm->ldnlen = dnlen;
1439  }
1440 /*@=compdef@*/
1441  }
1442 /*@=boundswrite@*/
1443  dnli = dnlFreeIterator(dnli);
1444  sx = rpmsxFree(sx);
1445  /*@=observertrans =dependenttrans@*/
1446 
1447  fsm->path = path;
1448  st->st_mode = st_mode; /* XXX restore st->st_mode */
1449 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1450  return rc;
1451 /*@=compdef@*/
1452 }
1453 
1454 #ifdef NOTYET
1455 
1460 static int fsmStat(/*@special@*/ /*@partial@*/ FSM_t fsm)
1461  /*@globals fileSystem, internalState @*/
1462  /*@modifies fsm, fileSystem, internalState @*/
1463 {
1464  int rc = 0;
1465 
1466  if (fsm->path != NULL) {
1467  int saveernno = errno;
1468  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS)
1469  ? FSM_LSTAT : FSM_STAT));
1470  if (rc == CPIOERR_ENOENT) {
1471  errno = saveerrno;
1472  rc = 0;
1473  fsm->exists = 0;
1474  } else if (rc == 0) {
1475  fsm->exists = 1;
1476  }
1477  } else {
1478  /* Skip %ghost files on build. */
1479  fsm->exists = 0;
1480  }
1481  return rc;
1482 }
1483 #endif
1484 
1485 #define IS_DEV_LOG(_x) \
1486  ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
1487  !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
1488  ((_x)[sizeof("/dev/log")-1] == '\0' || \
1489  (_x)[sizeof("/dev/log")-1] == ';'))
1490 
1491 /*@-boundsread@*/
1492 /*@-compmempass@*/
1493 int fsmStage(FSM_t fsm, fileStage stage)
1494 {
1495 #ifdef UNUSED
1496  fileStage prevStage = fsm->stage;
1497  const char * const prev = fileStageString(prevStage);
1498 #endif
1499  const char * const cur = fileStageString(stage);
1500  struct stat * st = &fsm->sb;
1501  struct stat * ost = &fsm->osb;
1502  int saveerrno = errno;
1503  int rc = fsm->rc;
1504  size_t left;
1505  int i;
1506 
1507 #define _fafilter(_a) \
1508  (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
1509  ? fileActionString(_a) : "")
1510 
1511  if (stage & FSM_DEAD) {
1512  /* do nothing */
1513  } else if (stage & FSM_INTERNAL) {
1514  if (_fsm_debug && !(stage & FSM_SYSCALL))
1515  rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1516  cur,
1517  (unsigned)st->st_mode, (int)st->st_nlink,
1518  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1519  (fsm->path ? fsm->path : ""),
1520  _fafilter(fsm->action));
1521  } else {
1522  const char * apath = NULL;
1523  if (fsm->path)
1524  (void) urlPath(fsm->path, &apath);
1525  fsm->stage = stage;
1526  if (_fsm_debug || !(stage & FSM_VERBOSE))
1527  rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1528  cur,
1529  (unsigned)st->st_mode, (int)st->st_nlink,
1530  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1531  (fsm->path ? apath + fsm->astriplen : ""),
1532  _fafilter(fsm->action));
1533  }
1534 #undef _fafilter
1535 
1536  /*@-branchstate@*/
1537  switch (stage) {
1538  case FSM_UNKNOWN:
1539  break;
1540  case FSM_PKGINSTALL:
1541  while (1) {
1542  /* Clean fsm, free'ing memory. Read next archive header. */
1543  rc = fsmUNSAFE(fsm, FSM_INIT);
1544 
1545  /* Exit on end-of-payload. */
1546  if (rc == CPIOERR_HDR_TRAILER) {
1547  rc = 0;
1548  /*@loopbreak@*/ break;
1549  }
1550 
1551  /* Exit on error. */
1552  if (rc) {
1553  fsm->postpone = 1;
1554  (void) fsmNext(fsm, FSM_UNDO);
1555  /*@loopbreak@*/ break;
1556  }
1557 
1558  /* Extract file from archive. */
1559  rc = fsmNext(fsm, FSM_PROCESS);
1560  if (rc) {
1561  (void) fsmNext(fsm, FSM_UNDO);
1562  /*@loopbreak@*/ break;
1563  }
1564 
1565  /* Notify on success. */
1566  (void) fsmNext(fsm, FSM_NOTIFY);
1567 
1568  rc = fsmNext(fsm, FSM_FINI);
1569  if (rc) {
1570  /*@loopbreak@*/ break;
1571  }
1572  }
1573  break;
1574  case FSM_PKGERASE:
1575  case FSM_PKGCOMMIT:
1576  while (1) {
1577  /* Clean fsm, free'ing memory. */
1578  rc = fsmUNSAFE(fsm, FSM_INIT);
1579 
1580  /* Exit on end-of-payload. */
1581  if (rc == CPIOERR_HDR_TRAILER) {
1582  rc = 0;
1583  /*@loopbreak@*/ break;
1584  }
1585 
1586  /* Rename/erase next item. */
1587  if (fsmNext(fsm, FSM_FINI))
1588  /*@loopbreak@*/ break;
1589  }
1590  break;
1591  case FSM_PKGBUILD:
1592  while (1) {
1593 
1594  rc = fsmUNSAFE(fsm, FSM_INIT);
1595 
1596  /* Exit on end-of-payload. */
1597  if (rc == CPIOERR_HDR_TRAILER) {
1598  rc = 0;
1599  /*@loopbreak@*/ break;
1600  }
1601 
1602  /* Exit on error. */
1603  if (rc) {
1604  fsm->postpone = 1;
1605  (void) fsmNext(fsm, FSM_UNDO);
1606  /*@loopbreak@*/ break;
1607  }
1608 
1609  /* Copy file into archive. */
1610  rc = fsmNext(fsm, FSM_PROCESS);
1611  if (rc) {
1612  (void) fsmNext(fsm, FSM_UNDO);
1613  /*@loopbreak@*/ break;
1614  }
1615 
1616  /* Notify on success. */
1617  (void) fsmNext(fsm, FSM_NOTIFY);
1618 
1619  if (fsmNext(fsm, FSM_FINI))
1620  /*@loopbreak@*/ break;
1621  }
1622 
1623  /* Flush partial sets of hard linked files. */
1624  if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) {
1625  int nlink, j;
1626  while ((fsm->li = fsm->links) != NULL) {
1627  fsm->links = fsm->li->next;
1628  fsm->li->next = NULL;
1629 
1630  /* Re-calculate link count for archive header. */
1631  for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) {
1632  if (fsm->li->filex[i] < 0)
1633  /*@innercontinue@*/ continue;
1634  nlink++;
1635  if (j == -1) j = i;
1636  }
1637  /* XXX force the contents out as well. */
1638 /*@-boundswrite@*/
1639  if (j != 0) {
1640  fsm->li->filex[0] = fsm->li->filex[j];
1641  fsm->li->filex[j] = -1;
1642  }
1643 /*@=boundswrite@*/
1644  fsm->li->sb.st_nlink = nlink;
1645 
1646  fsm->sb = fsm->li->sb; /* structure assignment */
1647  fsm->osb = fsm->sb; /* structure assignment */
1648 
1649  if (!rc) rc = writeLinkedFile(fsm);
1650 
1651  fsm->li = freeHardLink(fsm->li);
1652  }
1653  }
1654 
1655  if (!rc)
1656  rc = fsmNext(fsm, FSM_TRAILER);
1657 
1658  break;
1659  case FSM_CREATE:
1660  { rpmts ts = fsmGetTs(fsm);
1661 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
1662  fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) &&
1663  fsm->goal != FSM_PKGCOMMIT) ? 0 : 1);
1664 #undef _tsmask
1665  }
1666  fsm->path = _free(fsm->path);
1667  fsm->lpath = _free(fsm->lpath);
1668  fsm->opath = _free(fsm->opath);
1669  fsm->dnlx = _free(fsm->dnlx);
1670 
1671  fsm->ldn = _free(fsm->ldn);
1672  fsm->ldnalloc = fsm->ldnlen = 0;
1673 
1674  fsm->rdsize = fsm->wrsize = 0;
1675  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
1676  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
1677  if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
1678  fsm->rdsize = 8 * BUFSIZ;
1679  fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize);
1680  fsm->wrsize = 8 * BUFSIZ;
1681  fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize);
1682  }
1683 
1684  fsm->mkdirsdone = 0;
1685  fsm->ix = -1;
1686  fsm->links = NULL;
1687  fsm->li = NULL;
1688  errno = 0; /* XXX get rid of EBADF */
1689 
1690  /* Detect and create directories not explicitly in package. */
1691  if (fsm->goal == FSM_PKGINSTALL) {
1692 /*@-compdef@*/
1693  rc = fsmNext(fsm, FSM_MKDIRS);
1694 /*@=compdef@*/
1695  if (!rc) fsm->mkdirsdone = 1;
1696  }
1697 
1698  break;
1699  case FSM_INIT:
1700  fsm->path = _free(fsm->path);
1701  fsm->lpath = _free(fsm->lpath);
1702  fsm->postpone = 0;
1703  fsm->diskchecked = fsm->exists = 0;
1704  fsm->subdir = NULL;
1705  fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL);
1706  fsm->action = FA_UNKNOWN;
1707  fsm->osuffix = NULL;
1708  fsm->nsuffix = NULL;
1709 
1710  if (fsm->goal == FSM_PKGINSTALL) {
1711  /* Read next header from payload, checking for end-of-payload. */
1712  rc = fsmUNSAFE(fsm, FSM_NEXT);
1713  }
1714  if (rc) break;
1715 
1716  /* Identify mapping index. */
1717  fsm->ix = ((fsm->goal == FSM_PKGINSTALL)
1718  ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter));
1719 
1720 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_LIST)) {
1721  /* Detect end-of-loop and/or mapping error. */
1722 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_EXTRACT)) {
1723  if (fsm->ix < 0) {
1724  if (fsm->goal == FSM_PKGINSTALL) {
1725 #if 0
1727  _("archive file %s was not found in header file list\n"),
1728  fsm->path);
1729 #endif
1730 /*@-boundswrite@*/
1731  if (fsm->failedFile && *fsm->failedFile == NULL)
1732  *fsm->failedFile = xstrdup(fsm->path);
1733 /*@=boundswrite@*/
1734  rc = CPIOERR_UNMAPPED_FILE;
1735  } else {
1736  rc = CPIOERR_HDR_TRAILER;
1737  }
1738  break;
1739  }
1740 }
1741 
1742  /* On non-install, mode must be known so that dirs don't get suffix. */
1743  if (fsm->goal != FSM_PKGINSTALL) {
1744  rpmfi fi = fsmGetFi(fsm);
1745  st->st_mode = fi->fmodes[fsm->ix];
1746  }
1747 }
1748 
1749  /* Generate file path. */
1750  rc = fsmNext(fsm, FSM_MAP);
1751  if (rc) break;
1752 
1753  /* Perform lstat/stat for disk file. */
1754 #ifdef NOTYET
1755  rc = fsmStat(fsm);
1756 #else
1757  if (fsm->path != NULL &&
1758  !(fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode)))
1759  {
1760  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS)
1761  ? FSM_LSTAT : FSM_STAT));
1762  if (rc == CPIOERR_ENOENT) {
1763  errno = saveerrno;
1764  rc = 0;
1765  fsm->exists = 0;
1766  } else if (rc == 0) {
1767  fsm->exists = 1;
1768  }
1769  } else {
1770  /* Skip %ghost files on build. */
1771  fsm->exists = 0;
1772  }
1773 #endif
1774  fsm->diskchecked = 1;
1775  if (rc) break;
1776 
1777  /* On non-install, the disk file stat is what's remapped. */
1778 /*@-boundswrite@*/
1779  if (fsm->goal != FSM_PKGINSTALL)
1780  *st = *ost; /* structure assignment */
1781 /*@=boundswrite@*/
1782 
1783  /* Remap file perms, owner, and group. */
1784  rc = fsmMapAttrs(fsm);
1785  if (rc) break;
1786 
1787  fsm->postpone = XFA_SKIPPING(fsm->action);
1788  if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
1789  /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */
1790  if (!(S_ISDIR(st->st_mode) || S_ISLNK(st->st_mode))
1791  && (st->st_nlink > 1 || fsm->lpath != NULL))
1792  fsm->postpone = saveHardLink(fsm);
1793  /*@=evalorder@*/
1794  }
1795 if (fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_LIST) fsm->postpone = 1;
1796  break;
1797  case FSM_PRE:
1798  break;
1799  case FSM_MAP:
1800  rc = fsmMapPath(fsm);
1801  break;
1802  case FSM_MKDIRS:
1803  rc = fsmMkdirs(fsm);
1804  break;
1805  case FSM_RMDIRS:
1806  if (fsm->dnlx)
1807  rc = fsmRmdirs(fsm);
1808  break;
1809  case FSM_PROCESS:
1810  if (fsm->postpone) {
1811  if (fsm->goal == FSM_PKGINSTALL) {
1812  /* XXX Skip over file body, archive headers already done. */
1813  if (S_ISREG(st->st_mode))
1814  rc = fsmNext(fsm, FSM_EAT);
1815  }
1816  break;
1817  }
1818 
1819  if (fsm->goal == FSM_PKGBUILD) {
1820  if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
1821  break;
1822  if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
1823  struct hardLink_s * li, * prev;
1824 
1825 if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
1826  rc = writeLinkedFile(fsm);
1827  if (rc) break; /* W2DO? */
1828 
1829  for (li = fsm->links, prev = NULL; li; prev = li, li = li->next)
1830  if (li == fsm->li)
1831  /*@loopbreak@*/ break;
1832 
1833  if (prev == NULL)
1834  fsm->links = fsm->li->next;
1835  else
1836  prev->next = fsm->li->next;
1837  fsm->li->next = NULL;
1838  fsm->li = freeHardLink(fsm->li);
1839  } else {
1840  rc = writeFile(fsm, 1);
1841  }
1842  break;
1843  }
1844 
1845  if (fsm->goal != FSM_PKGINSTALL)
1846  break;
1847 
1848  if (S_ISREG(st->st_mode) && fsm->lpath != NULL) {
1849  const char * opath = fsm->opath;
1850  char * t = xmalloc(strlen(fsm->lpath+1) + strlen(fsm->suffix) + 1);
1851  (void) stpcpy(t, fsm->lpath+1);
1852  fsm->opath = t;
1853  /* XXX link(fsm->opath, fsm->path) */
1854  rc = fsmNext(fsm, FSM_LINK);
1855  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1856 /*@-boundswrite@*/
1857  *fsm->failedFile = xstrdup(fsm->path);
1858 /*@=boundswrite@*/
1859  }
1860  fsm->opath = _free(fsm->opath);
1861  fsm->opath = opath;
1862  break; /* XXX so that delayed hard links get skipped. */
1863  }
1864  if (S_ISREG(st->st_mode)) {
1865  const char * path = fsm->path;
1866  if (fsm->osuffix)
1867  fsm->path = fsmFsPath(fsm, st, NULL, NULL);
1868  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1869 
1870  if (rc == 0 && fsm->osuffix) {
1871  const char * opath = fsm->opath;
1872  fsm->opath = fsm->path;
1873  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
1874  rc = fsmNext(fsm, FSM_RENAME);
1875  if (!rc)
1877  _("%s saved as %s\n"),
1878  (fsm->opath ? fsm->opath : ""),
1879  (fsm->path ? fsm->path : ""));
1880  fsm->path = _free(fsm->path);
1881  fsm->opath = opath;
1882  }
1883 
1884  /*@-dependenttrans@*/
1885  fsm->path = path;
1886  /*@=dependenttrans@*/
1887  if (!(rc == CPIOERR_ENOENT)) return rc;
1888  rc = extractRegular(fsm);
1889  } else if (S_ISDIR(st->st_mode)) {
1890  mode_t st_mode = st->st_mode;
1891  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1892  if (rc == CPIOERR_ENOENT) {
1893  st->st_mode &= ~07777; /* XXX abuse st->st_mode */
1894  st->st_mode |= 00700;
1895  rc = fsmNext(fsm, FSM_MKDIR);
1896  st->st_mode = st_mode; /* XXX restore st->st_mode */
1897  }
1898  } else if (S_ISLNK(st->st_mode)) {
1899 assert(fsm->lpath != NULL);
1900  /*@=dependenttrans@*/
1901  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1902  if (rc == CPIOERR_ENOENT)
1903  rc = fsmNext(fsm, FSM_SYMLINK);
1904  } else if (S_ISFIFO(st->st_mode)) {
1905  mode_t st_mode = st->st_mode;
1906  /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
1907  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1908  if (rc == CPIOERR_ENOENT) {
1909  st->st_mode = 0000; /* XXX abuse st->st_mode */
1910  rc = fsmNext(fsm, FSM_MKFIFO);
1911  st->st_mode = st_mode; /* XXX restore st->st_mode */
1912  }
1913  } else if (S_ISCHR(st->st_mode) ||
1914  S_ISBLK(st->st_mode) ||
1915  /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
1916  {
1917  rc = fsmUNSAFE(fsm, FSM_VERIFY);
1918  if (rc == CPIOERR_ENOENT)
1919  rc = fsmNext(fsm, FSM_MKNOD);
1920  } else {
1921  /* XXX Repackaged payloads may be missing files. */
1922  if (fsm->repackaged)
1923  break;
1924 
1925  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
1926  if (!IS_DEV_LOG(fsm->path))
1928  }
1929  if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
1930  fsm->li->createdPath = fsm->li->linkIndex;
1931  rc = fsmMakeLinks(fsm);
1932  }
1933  break;
1934  case FSM_POST:
1935  break;
1936  case FSM_MKLINKS:
1937  rc = fsmMakeLinks(fsm);
1938  break;
1939  case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */
1940  if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
1941  rpmts ts = fsmGetTs(fsm);
1942  rpmfi fi = fsmGetFi(fsm);
1943  void * ptr;
1944  unsigned long long archivePos = fdGetCpioPos(fsm->cfd);
1945  if (archivePos > fi->archivePos) {
1946  fi->archivePos = archivePos;
1947  ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS,
1948  fi->archivePos, fi->archiveSize);
1949  }
1950  }
1951  break;
1952  case FSM_UNDO:
1953  if (fsm->postpone)
1954  break;
1955  if (fsm->goal == FSM_PKGINSTALL) {
1956  /* XXX only erase if temp fn w suffix is in use */
1957  if (fsm->sufbuf[0] != '\0')
1958  (void) fsmNext(fsm,
1959  (S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK));
1960 
1961 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
1962  if (fsm->dnlx)
1963  (void) fsmNext(fsm, FSM_RMDIRS);
1964 #endif
1965  errno = saveerrno;
1966  }
1967 /*@-boundswrite@*/
1968  if (fsm->failedFile && *fsm->failedFile == NULL)
1969  *fsm->failedFile = xstrdup(fsm->path);
1970 /*@=boundswrite@*/
1971  break;
1972  case FSM_FINI:
1973  if (!fsm->postpone && fsm->commit) {
1974  if (fsm->goal == FSM_PKGINSTALL)
1975  rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1)
1976  ? fsmCommitLinks(fsm) : fsmNext(fsm, FSM_COMMIT));
1977  if (fsm->goal == FSM_PKGCOMMIT)
1978  rc = fsmNext(fsm, FSM_COMMIT);
1979  if (fsm->goal == FSM_PKGERASE)
1980  rc = fsmNext(fsm, FSM_COMMIT);
1981  }
1982  fsm->path = _free(fsm->path);
1983  fsm->lpath = _free(fsm->lpath);
1984  fsm->opath = _free(fsm->opath);
1985 /*@-boundswrite@*/
1986  memset(st, 0, sizeof(*st));
1987  memset(ost, 0, sizeof(*ost));
1988 /*@=boundswrite@*/
1989  break;
1990  case FSM_COMMIT:
1991  /* Rename pre-existing modified or unmanaged file. */
1992  if (fsm->osuffix && fsm->diskchecked &&
1993  (fsm->exists || (fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode))))
1994  {
1995  const char * opath = fsm->opath;
1996  const char * path = fsm->path;
1997  fsm->opath = fsmFsPath(fsm, st, NULL, NULL);
1998  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
1999  rc = fsmNext(fsm, FSM_RENAME);
2000  if (!rc) {
2001  rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"),
2002  (fsm->opath ? fsm->opath : ""),
2003  (fsm->path ? fsm->path : ""));
2004  }
2005  fsm->path = _free(fsm->path);
2006  fsm->path = path;
2007  fsm->opath = _free(fsm->opath);
2008  fsm->opath = opath;
2009  }
2010 
2011  /* Remove erased files. */
2012  if (fsm->goal == FSM_PKGERASE) {
2013  if (fsm->action == FA_ERASE) {
2014  rpmfi fi = fsmGetFi(fsm);
2015  if (S_ISDIR(st->st_mode)) {
2016  rc = fsmNext(fsm, FSM_RMDIR);
2017  if (!rc) break;
2018  switch (rc) {
2019  case CPIOERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
2020  case CPIOERR_ENOTEMPTY:
2021  /* XXX make sure that build side permits %missingok on directories. */
2022  if (fsm->fflags & RPMFILE_MISSINGOK)
2023  /*@innerbreak@*/ break;
2024 
2025  /* XXX common error message. */
2026  rpmError(
2028  _("%s rmdir of %s failed: Directory not empty\n"),
2029  rpmfiTypeString(fi), fsm->path);
2030  /*@innerbreak@*/ break;
2031  default:
2032  rpmError(
2033  (strict_erasures ? RPMERR_RMDIR : RPMDEBUG_RMDIR),
2034  _("%s rmdir of %s failed: %s\n"),
2035  rpmfiTypeString(fi), fsm->path, strerror(errno));
2036  /*@innerbreak@*/ break;
2037  }
2038  } else {
2039  rc = fsmNext(fsm, FSM_UNLINK);
2040  if (!rc) break;
2041  switch (rc) {
2042  case CPIOERR_ENOENT:
2043  if (fsm->fflags & RPMFILE_MISSINGOK)
2044  /*@innerbreak@*/ break;
2045  /*@fallthrough@*/
2046  default:
2047  rpmError(
2049  _(" %s: unlink of %s failed: %s\n"),
2050  rpmfiTypeString(fi), fsm->path, strerror(errno));
2051  /*@innerbreak@*/ break;
2052  }
2053  }
2054  }
2055  /* XXX Failure to remove is not (yet) cause for failure. */
2056  if (!strict_erasures) rc = 0;
2057  break;
2058  }
2059 
2060  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2061 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_EXTRACT)) {
2062  if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) {
2063  /* Rename temporary to final file name. */
2064  if (!S_ISDIR(st->st_mode) &&
2065  (fsm->subdir || fsm->suffix || fsm->nsuffix))
2066  {
2067  fsm->opath = fsm->path;
2068  fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix);
2069  rc = fsmNext(fsm, FSM_RENAME);
2070  if (rc)
2071  (void) Unlink(fsm->opath);
2072  else if (fsm->nsuffix) {
2073  const char * opath = fsmFsPath(fsm, st, NULL, NULL);
2074  rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"),
2075  (opath ? opath : ""),
2076  (fsm->path ? fsm->path : ""));
2077  opath = _free(opath);
2078  }
2079  fsm->opath = _free(fsm->opath);
2080  }
2081  /*
2082  * Set file security context (if not disabled).
2083  */
2084  if (!rc && !getuid()) {
2085  rc = fsmMapFContext(fsm);
2086  if (!rc)
2087  rc = fsmNext(fsm, FSM_LSETFCON);
2088  fsm->fcontext = NULL;
2089  }
2090  if (S_ISLNK(st->st_mode)) {
2091  if (!rc && !getuid())
2092  rc = fsmNext(fsm, FSM_LCHOWN);
2093  } else {
2094  if (!rc && !getuid())
2095  rc = fsmNext(fsm, FSM_CHOWN);
2096  if (!rc)
2097  rc = fsmNext(fsm, FSM_CHMOD);
2098  if (!rc) {
2099  time_t mtime = st->st_mtime;
2100  rpmfi fi = fsmGetFi(fsm);
2101  if (fi->fmtimes)
2102  st->st_mtime = fi->fmtimes[fsm->ix];
2103  rc = fsmNext(fsm, FSM_UTIME);
2104  st->st_mtime = mtime;
2105  }
2106  }
2107  }
2108 }
2109 
2110  /* Notify on success. */
2111  if (!rc) rc = fsmNext(fsm, FSM_NOTIFY);
2112  else if (fsm->failedFile && *fsm->failedFile == NULL) {
2113 /*@-boundswrite@*/
2114  *fsm->failedFile = fsm->path;
2115 /*@=boundswrite@*/
2116  fsm->path = NULL;
2117  }
2118  break;
2119  case FSM_DESTROY:
2120  fsm->path = _free(fsm->path);
2121 
2122  /* Check for hard links missing from payload. */
2123  while ((fsm->li = fsm->links) != NULL) {
2124  fsm->links = fsm->li->next;
2125  fsm->li->next = NULL;
2126  if (fsm->goal == FSM_PKGINSTALL &&
2127  fsm->commit && fsm->li->linksLeft)
2128  {
2129  for (i = 0 ; i < fsm->li->linksLeft; i++) {
2130  if (fsm->li->filex[i] < 0)
2131  /*@innercontinue@*/ continue;
2133  if (fsm->failedFile && *fsm->failedFile == NULL) {
2134  fsm->ix = fsm->li->filex[i];
2135  if (!fsmNext(fsm, FSM_MAP)) {
2136 /*@-boundswrite@*/
2137  *fsm->failedFile = fsm->path;
2138 /*@=boundswrite@*/
2139  fsm->path = NULL;
2140  }
2141  }
2142  /*@loopbreak@*/ break;
2143  }
2144  }
2145  if (fsm->goal == FSM_PKGBUILD &&
2146  (fsm->mapFlags & CPIO_ALL_HARDLINKS))
2147  {
2149  }
2150  fsm->li = freeHardLink(fsm->li);
2151  }
2152  fsm->ldn = _free(fsm->ldn);
2153  fsm->ldnalloc = fsm->ldnlen = 0;
2154  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
2155  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
2156  break;
2157  case FSM_VERIFY:
2158  if (fsm->diskchecked && !fsm->exists) {
2159  rc = CPIOERR_ENOENT;
2160  break;
2161  }
2162  if (S_ISREG(st->st_mode)) {
2163  char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
2164 /*@-boundswrite@*/
2165  (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
2166 /*@=boundswrite@*/
2167  /*
2168  * XXX HP-UX (and other os'es) don't permit unlink on busy
2169  * XXX files.
2170  */
2171  fsm->opath = fsm->path;
2172  fsm->path = path;
2173  rc = fsmNext(fsm, FSM_RENAME);
2174  if (!rc)
2175  (void) fsmNext(fsm, FSM_UNLINK);
2176  else
2177  rc = CPIOERR_UNLINK_FAILED;
2178  fsm->path = fsm->opath;
2179  fsm->opath = NULL;
2180  return (rc ? rc : CPIOERR_ENOENT); /* XXX HACK */
2181  /*@notreached@*/ break;
2182  } else if (S_ISDIR(st->st_mode)) {
2183  if (S_ISDIR(ost->st_mode)) return 0;
2184  if (S_ISLNK(ost->st_mode)) {
2185  rc = fsmUNSAFE(fsm, FSM_STAT);
2186  if (rc == CPIOERR_ENOENT) rc = 0;
2187  if (rc) break;
2188  errno = saveerrno;
2189  if (S_ISDIR(ost->st_mode)) return 0;
2190  }
2191  } else if (S_ISLNK(st->st_mode)) {
2192  if (S_ISLNK(ost->st_mode)) {
2193  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
2194  rc = fsmUNSAFE(fsm, FSM_READLINK);
2195  errno = saveerrno;
2196  if (rc) break;
2197  if (!strcmp(fsm->lpath, fsm->rdbuf)) return 0;
2198  }
2199  } else if (S_ISFIFO(st->st_mode)) {
2200  if (S_ISFIFO(ost->st_mode)) return 0;
2201  } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
2202  if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
2203  (ost->st_rdev == st->st_rdev)) return 0;
2204  } else if (S_ISSOCK(st->st_mode)) {
2205  if (S_ISSOCK(ost->st_mode)) return 0;
2206  }
2207  /* XXX shouldn't do this with commit/undo. */
2208  rc = 0;
2209  if (fsm->stage == FSM_PROCESS) rc = fsmNext(fsm, FSM_UNLINK);
2210  if (rc == 0) rc = CPIOERR_ENOENT;
2211  return (rc ? rc : CPIOERR_ENOENT); /* XXX HACK */
2212  /*@notreached@*/ break;
2213 
2214  case FSM_UNLINK:
2215  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2216  if (fsm->mapFlags & CPIO_SBIT_CHECK) {
2217  struct stat stb;
2218  if (Lstat(fsm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) {
2219  /* XXX rc = fsmNext(fsm, FSM_CHMOD); instead */
2220  int xx = chmod(fsm->path, stb.st_mode & 0777);
2221  }
2222  }
2223  rc = Unlink(fsm->path);
2224  if (_fsm_debug && (stage & FSM_SYSCALL))
2225  rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
2226  fsm->path, (rc < 0 ? strerror(errno) : ""));
2227  if (rc < 0)
2228  rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_UNLINK_FAILED);
2229  break;
2230  case FSM_RENAME:
2231  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2232  if (fsm->mapFlags & CPIO_SBIT_CHECK) {
2233  struct stat stb;
2234  if (Lstat(fsm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) {
2235  /* XXX rc = fsmNext(fsm, FSM_CHMOD); instead */
2236  int xx = chmod(fsm->path, stb.st_mode & 0777);
2237  }
2238  }
2239  rc = Rename(fsm->opath, fsm->path);
2240  /* XXX Repackaged payloads may be missing files. */
2241  if (fsm->repackaged)
2242  rc = 0;
2243 #if defined(ETXTBSY)
2244  if (rc && errno == ETXTBSY) {
2245  char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
2246  (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
2247  /*
2248  * XXX HP-UX (and other os'es) don't permit rename to busy
2249  * XXX files.
2250  */
2251  rc = Rename(fsm->path, path);
2252  if (!rc) rc = Rename(fsm->opath, fsm->path);
2253  }
2254 #endif
2255  if (_fsm_debug && (stage & FSM_SYSCALL))
2256  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
2257  fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
2258  if (rc < 0) rc = CPIOERR_RENAME_FAILED;
2259  break;
2260  case FSM_MKDIR:
2261  rc = Mkdir(fsm->path, (st->st_mode & 07777));
2262  if (_fsm_debug && (stage & FSM_SYSCALL))
2263  rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2264  fsm->path, (unsigned)(st->st_mode & 07777),
2265  (rc < 0 ? strerror(errno) : ""));
2266  if (rc < 0) rc = CPIOERR_MKDIR_FAILED;
2267  break;
2268  case FSM_RMDIR:
2269  rc = Rmdir(fsm->path);
2270  if (_fsm_debug && (stage & FSM_SYSCALL))
2271  rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
2272  fsm->path, (rc < 0 ? strerror(errno) : ""));
2273  if (rc < 0)
2274  switch (errno) {
2275  case ENOENT: rc = CPIOERR_ENOENT; /*@switchbreak@*/ break;
2276  case ENOTEMPTY: rc = CPIOERR_ENOTEMPTY; /*@switchbreak@*/ break;
2277  default: rc = CPIOERR_RMDIR_FAILED; /*@switchbreak@*/ break;
2278  }
2279  break;
2280  case FSM_LSETFCON:
2281  { const char * fsmpath = NULL;
2282  if (fsm->fcontext == NULL || *fsm->fcontext == '\0'
2283  || !strcmp(fsm->fcontext, "<<none>>"))
2284  break;
2285  (void) urlPath(fsm->path, &fsmpath); /* XXX fsm->path */
2286  rc = lsetfilecon(fsmpath, (security_context_t)fsm->fcontext);
2287  if (_fsm_debug && (stage & FSM_SYSCALL))
2288  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
2289  fsm->path, fsm->fcontext,
2290  (rc < 0 ? strerror(errno) : ""));
2291  if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : CPIOERR_LSETFCON_FAILED);
2292  } break;
2293  case FSM_CHOWN:
2294  rc = Chown(fsm->path, st->st_uid, st->st_gid);
2295  if (_fsm_debug && (stage & FSM_SYSCALL))
2296  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2297  fsm->path, (int)st->st_uid, (int)st->st_gid,
2298  (rc < 0 ? strerror(errno) : ""));
2299  if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
2300  break;
2301  case FSM_LCHOWN:
2302 #if ! CHOWN_FOLLOWS_SYMLINK
2303  rc = Lchown(fsm->path, st->st_uid, st->st_gid);
2304  if (_fsm_debug && (stage & FSM_SYSCALL))
2305  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2306  fsm->path, (int)st->st_uid, (int)st->st_gid,
2307  (rc < 0 ? strerror(errno) : ""));
2308  if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
2309 #endif
2310  break;
2311  case FSM_CHMOD:
2312  rc = Chmod(fsm->path, (st->st_mode & 07777));
2313  if (_fsm_debug && (stage & FSM_SYSCALL))
2314  rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2315  fsm->path, (unsigned)(st->st_mode & 07777),
2316  (rc < 0 ? strerror(errno) : ""));
2317  if (rc < 0) rc = CPIOERR_CHMOD_FAILED;
2318  break;
2319  case FSM_UTIME:
2320  { struct utimbuf stamp;
2321  stamp.actime = st->st_mtime;
2322  stamp.modtime = st->st_mtime;
2323  rc = Utime(fsm->path, &stamp);
2324  if (_fsm_debug && (stage & FSM_SYSCALL))
2325  rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0x%x) %s\n", cur,
2326  fsm->path, (unsigned)st->st_mtime,
2327  (rc < 0 ? strerror(errno) : ""));
2328  if (rc < 0) rc = CPIOERR_UTIME_FAILED;
2329  }
2330  break;
2331  case FSM_SYMLINK:
2332  rc = Symlink(fsm->lpath, fsm->path);
2333  if (_fsm_debug && (stage & FSM_SYSCALL))
2334  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
2335  fsm->lpath, fsm->path, (rc < 0 ? strerror(errno) : ""));
2336  if (rc < 0) rc = CPIOERR_SYMLINK_FAILED;
2337  break;
2338  case FSM_LINK:
2339  rc = Link(fsm->opath, fsm->path);
2340  if (_fsm_debug && (stage & FSM_SYSCALL))
2341  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
2342  fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
2343  if (rc < 0) rc = CPIOERR_LINK_FAILED;
2344  break;
2345  case FSM_MKFIFO:
2346  rc = Mkfifo(fsm->path, (st->st_mode & 07777));
2347  if (_fsm_debug && (stage & FSM_SYSCALL))
2348  rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2349  fsm->path, (unsigned)(st->st_mode & 07777),
2350  (rc < 0 ? strerror(errno) : ""));
2351  if (rc < 0) rc = CPIOERR_MKFIFO_FAILED;
2352  break;
2353  case FSM_MKNOD:
2354  /*@-unrecog -portability @*/ /* FIX: check S_IFIFO or dev != 0 */
2355  rc = Mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev);
2356  /*@=unrecog =portability @*/
2357  if (_fsm_debug && (stage & FSM_SYSCALL))
2358  rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur,
2359  fsm->path, (unsigned)(st->st_mode & ~07777),
2360  (unsigned)st->st_rdev,
2361  (rc < 0 ? strerror(errno) : ""));
2362  if (rc < 0) rc = CPIOERR_MKNOD_FAILED;
2363  break;
2364  case FSM_LSTAT:
2365  rc = Lstat(fsm->path, ost);
2366  if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT)
2367  rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
2368  fsm->path, (rc < 0 ? strerror(errno) : ""));
2369  if (rc < 0) {
2370  rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_LSTAT_FAILED);
2371  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2372  }
2373  break;
2374  case FSM_STAT:
2375  rc = Stat(fsm->path, ost);
2376  if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT)
2377  rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
2378  fsm->path, (rc < 0 ? strerror(errno) : ""));
2379  if (rc < 0) {
2380  rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_STAT_FAILED);
2381  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2382  }
2383  break;
2384  case FSM_READLINK:
2385  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
2386 /*@-boundswrite@*/
2387  rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1);
2388 /*@=boundswrite@*/
2389  if (_fsm_debug && (stage & FSM_SYSCALL))
2390  rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur,
2391  fsm->path, (int)(fsm->rdsize -1), (rc < 0 ? strerror(errno) : ""));
2392  if (rc < 0) rc = CPIOERR_READLINK_FAILED;
2393  else {
2394  fsm->rdnb = rc;
2395 /*@-boundswrite@*/
2396  fsm->rdbuf[fsm->rdnb] = '\0';
2397 /*@=boundswrite@*/
2398  rc = 0;
2399  }
2400  break;
2401  case FSM_CHROOT:
2402  break;
2403 
2404  case FSM_NEXT:
2405  rc = fsmUNSAFE(fsm, FSM_HREAD);
2406  if (rc) break;
2407  if (!strcmp(fsm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */
2408  fsm->path = _free(fsm->path);
2409  rc = CPIOERR_HDR_TRAILER;
2410  }
2411  if (!rc)
2412  rc = fsmNext(fsm, FSM_POS);
2413  break;
2414  case FSM_EAT:
2415  for (left = st->st_size; left > 0; left -= fsm->rdnb) {
2416  fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
2417  rc = fsmNext(fsm, FSM_DREAD);
2418  if (rc)
2419  /*@loopbreak@*/ break;
2420  }
2421  break;
2422  case FSM_POS:
2423  left = (fsm->blksize - (fdGetCpioPos(fsm->cfd) % fsm->blksize)) % fsm->blksize;
2424  if (left) {
2425  fsm->wrlen = left;
2426  (void) fsmNext(fsm, FSM_DREAD);
2427  }
2428  break;
2429  case FSM_PAD:
2430  left = (fsm->blksize - (fdGetCpioPos(fsm->cfd) % fsm->blksize)) % fsm->blksize;
2431  if (left) {
2432 /*@-boundswrite@*/
2433  memset(fsm->rdbuf, 0, left);
2434 /*@=boundswrite@*/
2435  /* XXX DWRITE uses rdnb for I/O length. */
2436  fsm->rdnb = left;
2437  (void) fsmNext(fsm, FSM_DWRITE);
2438  }
2439  break;
2440  case FSM_TRAILER:
2441  rc = (*fsm->trailerWrite) (fsm); /* Write payload trailer. */
2442  break;
2443  case FSM_HREAD:
2444  rc = fsmNext(fsm, FSM_POS);
2445  if (!rc)
2446  rc = (*fsm->headerRead) (fsm, st); /* Read next payload header. */
2447  break;
2448  case FSM_HWRITE:
2449  rc = (*fsm->headerWrite) (fsm, st); /* Write next payload header. */
2450  break;
2451  case FSM_DREAD:
2452 /*@-boundswrite@*/
2453  fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd);
2454 /*@=boundswrite@*/
2455  if (_fsm_debug && (stage & FSM_SYSCALL))
2456  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n",
2457  cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"),
2458  (int)fsm->wrlen, (int)fsm->rdnb);
2459  if (fsm->rdnb != fsm->wrlen || Ferror(fsm->cfd))
2460  rc = CPIOERR_READ_FAILED;
2461  if (fsm->rdnb > 0)
2462  fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb);
2463  break;
2464  case FSM_DWRITE:
2465  fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd);
2466  if (_fsm_debug && (stage & FSM_SYSCALL))
2467  rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n",
2468  cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"),
2469  (int)fsm->rdnb, (int)fsm->wrnb);
2470  if (fsm->rdnb != fsm->wrnb || Ferror(fsm->cfd))
2471  rc = CPIOERR_WRITE_FAILED;
2472  if (fsm->wrnb > 0)
2473  fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb);
2474  break;
2475 
2476  case FSM_ROPEN:
2477  fsm->rfd = Fopen(fsm->path, "r");
2478  if (fsm->rfd == NULL || Ferror(fsm->rfd)) {
2479  if (fsm->rfd != NULL) (void) fsmNext(fsm, FSM_RCLOSE);
2480  fsm->rfd = NULL;
2481  rc = CPIOERR_OPEN_FAILED;
2482  break;
2483  }
2484  if (_fsm_debug && (stage & FSM_SYSCALL))
2485  rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur,
2486  fsm->path, fsm->rfd, fsm->rdbuf);
2487  break;
2488  case FSM_READ:
2489 /*@-boundswrite@*/
2490  fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd);
2491 /*@=boundswrite@*/
2492  if (_fsm_debug && (stage & FSM_SYSCALL))
2493  rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n",
2494  cur, (int)fsm->rdlen, (int)fsm->rdnb);
2495  if (fsm->rdnb != fsm->rdlen || Ferror(fsm->rfd))
2496  rc = CPIOERR_READ_FAILED;
2497  break;
2498  case FSM_RCLOSE:
2499  if (fsm->rfd != NULL) {
2500  if (_fsm_debug && (stage & FSM_SYSCALL))
2501  rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd);
2502  (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
2503  fdstat_op(fsm->rfd, FDSTAT_DIGEST));
2504  (void) Fclose(fsm->rfd);
2505  errno = saveerrno;
2506  }
2507  fsm->rfd = NULL;
2508  break;
2509  case FSM_WOPEN:
2510  fsm->wfd = Fopen(fsm->path, "w");
2511  if (fsm->wfd == NULL || Ferror(fsm->wfd)) {
2512  if (fsm->wfd != NULL) (void) fsmNext(fsm, FSM_WCLOSE);
2513  fsm->wfd = NULL;
2514  rc = CPIOERR_OPEN_FAILED;
2515  }
2516  if (_fsm_debug && (stage & FSM_SYSCALL))
2517  rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur,
2518  fsm->path, fsm->wfd, fsm->wrbuf);
2519  break;
2520  case FSM_WRITE:
2521  fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd);
2522  if (_fsm_debug && (stage & FSM_SYSCALL))
2523  rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n",
2524  cur, (int)fsm->rdnb, (int)fsm->wrnb);
2525  if (fsm->rdnb != fsm->wrnb || Ferror(fsm->wfd))
2526  rc = CPIOERR_WRITE_FAILED;
2527  break;
2528  case FSM_WCLOSE:
2529  if (fsm->wfd != NULL) {
2530  if (_fsm_debug && (stage & FSM_SYSCALL))
2531  rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd);
2532  (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
2533  fdstat_op(fsm->wfd, FDSTAT_DIGEST));
2534  (void) Fclose(fsm->wfd);
2535  errno = saveerrno;
2536  }
2537  fsm->wfd = NULL;
2538  break;
2539 
2540  default:
2541  break;
2542  }
2543  /*@=branchstate@*/
2544 
2545  if (!(stage & FSM_INTERNAL)) {
2546  fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc);
2547  }
2548  return rc;
2549 }
2550 /*@=compmempass@*/
2551 /*@=boundsread@*/
2552 
2553 /*@observer@*/ const char * fileActionString(fileAction a)
2554 {
2555  switch (a) {
2556  case FA_UNKNOWN: return "unknown";
2557  case FA_CREATE: return "create";
2558  case FA_COPYOUT: return "copyout";
2559  case FA_COPYIN: return "copyin";
2560  case FA_BACKUP: return "backup";
2561  case FA_SAVE: return "save";
2562  case FA_SKIP: return "skip";
2563  case FA_ALTNAME: return "altname";
2564  case FA_ERASE: return "erase";
2565  case FA_SKIPNSTATE: return "skipnstate";
2566  case FA_SKIPNETSHARED: return "skipnetshared";
2567  case FA_SKIPCOLOR: return "skipcolor";
2568  default: return "???";
2569  }
2570  /*@notreached@*/
2571 }
2572 
2573 /*@observer@*/ const char * fileStageString(fileStage a) {
2574  switch(a) {
2575  case FSM_UNKNOWN: return "unknown";
2576 
2577  case FSM_PKGINSTALL:return "INSTALL";
2578  case FSM_PKGERASE: return "ERASE";
2579  case FSM_PKGBUILD: return "BUILD";
2580  case FSM_PKGCOMMIT: return "COMMIT";
2581  case FSM_PKGUNDO: return "UNDO";
2582 
2583  case FSM_CREATE: return "create";
2584  case FSM_INIT: return "init";
2585  case FSM_MAP: return "map";
2586  case FSM_MKDIRS: return "mkdirs";
2587  case FSM_RMDIRS: return "rmdirs";
2588  case FSM_PRE: return "pre";
2589  case FSM_PROCESS: return "process";
2590  case FSM_POST: return "post";
2591  case FSM_MKLINKS: return "mklinks";
2592  case FSM_NOTIFY: return "notify";
2593  case FSM_UNDO: return "undo";
2594  case FSM_FINI: return "fini";
2595  case FSM_COMMIT: return "commit";
2596  case FSM_DESTROY: return "destroy";
2597  case FSM_VERIFY: return "verify";
2598 
2599  case FSM_UNLINK: return "Unlink";
2600  case FSM_RENAME: return "Rename";
2601  case FSM_MKDIR: return "Mkdir";
2602  case FSM_RMDIR: return "rmdir";
2603  case FSM_LSETFCON: return "lsetfcon";
2604  case FSM_CHOWN: return "chown";
2605  case FSM_LCHOWN: return "lchown";
2606  case FSM_CHMOD: return "chmod";
2607  case FSM_UTIME: return "utime";
2608  case FSM_SYMLINK: return "symlink";
2609  case FSM_LINK: return "Link";
2610  case FSM_MKFIFO: return "mkfifo";
2611  case FSM_MKNOD: return "mknod";
2612  case FSM_LSTAT: return "Lstat";
2613  case FSM_STAT: return "Stat";
2614  case FSM_READLINK: return "Readlink";
2615  case FSM_CHROOT: return "chroot";
2616 
2617  case FSM_NEXT: return "next";
2618  case FSM_EAT: return "eat";
2619  case FSM_POS: return "pos";
2620  case FSM_PAD: return "pad";
2621  case FSM_TRAILER: return "trailer";
2622  case FSM_HREAD: return "hread";
2623  case FSM_HWRITE: return "hwrite";
2624  case FSM_DREAD: return "Fread";
2625  case FSM_DWRITE: return "Fwrite";
2626 
2627  case FSM_ROPEN: return "Fopen";
2628  case FSM_READ: return "Fread";
2629  case FSM_RCLOSE: return "Fclose";
2630  case FSM_WOPEN: return "Fopen";
2631  case FSM_WRITE: return "Fwrite";
2632  case FSM_WCLOSE: return "Fclose";
2633 
2634  default: return "???";
2635  }
2636  /*@noteached@*/
2637 }