rpm  5.4.15
fsm.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h> /* XXX urlPath, fdGetCpioPos */
9 #include <rpmcb.h> /* XXX fnpyKey */
10 #include "rpmsq.h"
11 #include <rpmsx.h>
12 #if defined(SUPPORT_AR_PAYLOADS)
13 #include "ar.h"
14 #endif
15 #include "cpio.h"
16 #include "tar.h"
17 #include "ugid.h" /* XXX unameToUid() and gnameToGid() */
18 
19 #include <rpmtag.h>
20 #include <rpmtypes.h>
21 #define _RPMDB_INTERNAL
22 #include <rpmdb.h>
23 
24 #define _RPMFI_INTERNAL
25 #include "rpmfi.h"
26 
27 #define _IOSM_INTERNAL
28 #include <fsm.h>
29 #define fsmUNSAFE fsmStage
30 
31 #define _USE_RPMTE
32 #if defined(_USE_RPMTE)
33 #include "rpmte.h"
34 #endif
35 #include "rpmts.h"
36 
37 #include "debug.h"
38 
39 /*@access FD_t @*/ /* XXX void ptr args */
40 /*@access FSMI_t @*/
41 /*@access IOSM_t @*/
42 /*@access IOSMI_t @*/
43 
44 /*@access rpmfi @*/
45 
46 /*@access rpmsx @*/ /* XXX cast */
47 /*@access rpmte @*/ /* XXX cast */
48 /*@access rpmts @*/ /* XXX cast */
49 
50 #ifdef __cplusplus
51 GENfree(const void *)
52 GENfree(unsigned short *)
53 GENfree(DNLI_t)
54 GENfree(FSMI_t)
55 #endif /* __cplusplus */
56 
57 #define alloca_strdup(_s) strcpy((char *)alloca(strlen(_s)+1), (_s))
58 
59 #define _FSM_DEBUG 0
60 /*@unchecked@*/
62 
63 /*@-exportheadervar@*/
64 /*@unchecked@*/
65 int _fsm_threads = 0;
66 /*@=exportheadervar@*/
67 
73 static rpmts fsmGetTs(const IOSM_t fsm)
74  /*@*/
75 {
76  const FSMI_t iter = fsm->iter;
77  /*@-compdef -refcounttrans -retexpose -usereleased @*/
78  return (rpmts) (iter ? iter->ts : NULL);
79  /*@=compdef =refcounttrans =retexpose =usereleased @*/
80 }
81 
87 static rpmfi fsmGetFi(const IOSM_t fsm)
88  /*@*/
89 {
90  const FSMI_t iter = fsm->iter;
91  /*@-compdef -refcounttrans -retexpose -usereleased @*/
92  return (rpmfi) (iter ? iter->fi : NULL);
93  /*@=compdef =refcounttrans =retexpose =usereleased @*/
94 }
95 
96 #define SUFFIX_RPMORIG ".rpmorig"
97 #define SUFFIX_RPMSAVE ".rpmsave"
98 #define SUFFIX_RPMNEW ".rpmnew"
99 
108 static /*@only@*//*@null@*/
109 const char * fsmFsPath(/*@special@*/ /*@null@*/ const IOSM_t fsm,
110  /*@null@*/ const struct stat * st,
111  /*@null@*/ const char * subdir,
112  /*@null@*/ const char * suffix)
113  /*@uses fsm->dirName, fsm->baseName */
114  /*@*/
115 {
116  const char * s = NULL;
117 
118  if (fsm) {
119  char * t;
120  int nb;
121  nb = strlen(fsm->dirName) +
122  (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) +
123  (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) +
124  strlen(fsm->baseName) + 1;
125  s = t = (char *) xmalloc(nb);
126  t = stpcpy(t, fsm->dirName);
127  if (st && !S_ISDIR(st->st_mode))
128  if (subdir) t = stpcpy(t, subdir);
129  t = stpcpy(t, fsm->baseName);
130  if (st && !S_ISDIR(st->st_mode))
131  if (suffix) t = stpcpy(t, suffix);
132  }
133  return s;
134 }
135 
141 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * _iter)
142  /*@globals fileSystem @*/
143  /*@modifies fileSystem @*/
144 {
145  FSMI_t iter = (FSMI_t) _iter;
146  if (iter) {
147  iter->fi = rpmfiUnlink(iter->fi, "mapIterator");
148 /*@-internalglobs@*/ /* XXX rpmswExit() */
149  (void)rpmtsFree(iter->ts);
150  iter->ts = NULL;
151 /*@=internalglobs@*/
152  }
153  return _free(iter);
154 }
155 
162 static void *
164  /*@modifies fi @*/
165 {
166  FSMI_t iter = NULL;
167 
168  iter = (FSMI_t) xcalloc(1, sizeof(*iter));
169 /*@-assignexpose -castexpose @*/
170  iter->fi = rpmfiLink(fi, "mapIterator");
171 /*@=assignexpose =castexpose @*/
172  iter->reverse = reverse;
173  iter->i = (iter->reverse ? (fi->fc - 1) : 0);
174  iter->isave = iter->i;
175  return iter;
176 }
177 
183 static int mapNextIterator(/*@null@*/ void * _iter)
184  /*@*/
185 {
186  FSMI_t iter = (FSMI_t) _iter;
187  int i = -1;
188 
189  if (iter) {
190 /*@-onlytrans@*/
191  const rpmfi fi = (rpmfi) iter->fi;
192 /*@=onlytrans@*/
193  if (iter->reverse) {
194  if (iter->i >= 0) i = iter->i--;
195  } else {
196  if (iter->i < (int)fi->fc) i = iter->i++;
197  }
198  iter->isave = i;
199  }
200  return i;
201 }
202 
205 static int cpioStrCmp(const void * a, const void * b)
206  /*@*/
207 {
208  const char * aurl = *(const char **)a;
209  const char * burl = *(const char **)b;
210  const char * afn = NULL;
211  const char * bfn = NULL;
212 
213  (void) urlPath(aurl, &afn);
214  (void) urlPath(burl, &bfn);
215 
216 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES
217  /* XXX Some rpm-2.4 packages from 1997 have basename only in payloads. */
218  if (strchr(afn, '/') == NULL)
219  bfn = strrchr(bfn, '/') + 1;
220 #endif
221 
222  /* Match rpm-4.0 payloads with ./ prefixes. */
223  if (afn[0] == '.' && afn[1] == '/') afn += 2;
224  if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
225 
226  /* If either path is absolute, make it relative to '/'. */
227  if (afn[0] == '/') afn += 1;
228  if (bfn[0] == '/') bfn += 1;
229 
230  return strcmp(afn, bfn);
231 }
232 
239 static int mapFind(/*@null@*/ FSMI_t iter, const char * fsmPath)
240  /*@modifies iter @*/
241 {
242  int ix = -1;
243 
244  if (iter) {
245 /*@-onlytrans@*/
246  const rpmfi fi = (rpmfi) iter->fi;
247 /*@=onlytrans@*/
248  size_t fc = rpmfiFC(fi);
249  if (fi && fc > 0 && fi->apath && fsmPath && *fsmPath) {
250  const char ** p = NULL;
251 
252  if (fi->apath != NULL)
253  p = (const char **)
254  bsearch(&fsmPath, fi->apath, fc, sizeof(fsmPath),
255  cpioStrCmp);
256  if (p) {
257  iter->i = p - fi->apath;
258  ix = mapNextIterator(iter);
259  }
260  }
261  }
262  return ix;
263 }
264 
268 typedef struct dnli_s {
270 /*@only@*/ /*@null@*/
271  char * active;
272  int reverse;
273  int isave;
274  int i;
275 } * DNLI_t;
276 
282 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/const void * _dnli)
283  /*@modifies a @*/
284 {
285  if (_dnli) {
286  DNLI_t dnli = (DNLI_t) _dnli;
287  if (dnli->active) free(dnli->active);
288  }
289  return _free(_dnli);
290 }
291 
294 static inline int dnlCount(/*@null@*/ const DNLI_t dnli)
295  /*@*/
296 {
297  return (int) (dnli ? dnli->fi->dc : 0);
298 }
299 
302 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli)
303  /*@*/
304 {
305  return (dnli ? dnli->isave : -1);
306 }
307 
314 /*@-usereleased@*/
315 static /*@only@*/ /*@null@*/
316 void * dnlInitIterator(/*@special@*/ const IOSM_t fsm,
317  int reverse)
318  /*@uses fsm->iter @*/
319  /*@*/
320 {
321  rpmfi fi = fsmGetFi(fsm);
322  const char * dnl;
323  DNLI_t dnli;
324  int i, j;
325 
326  if (fi == NULL)
327  return NULL;
328  dnli = (DNLI_t) xcalloc(1, sizeof(*dnli));
329  dnli->fi = fi;
330  dnli->reverse = reverse;
331  dnli->i = (int) (reverse ? fi->dc : 0);
332 
333  if (fi->dc) {
334  dnli->active = (char *) xcalloc(fi->dc, sizeof(*dnli->active));
335 
336  /* Identify parent directories not skipped. */
337  if ((fi = rpmfiInit(fi, 0)) != NULL)
338  while ((i = rpmfiNext(fi)) >= 0) {
339  if (!iosmFileActionSkipped(fi->actions[i])) dnli->active[fi->dil[i]] = 1;
340  }
341 
342  /* Exclude parent directories that are explicitly included. */
343  if ((fi = rpmfiInit(fi, 0)) != NULL)
344  while ((i = rpmfiNext(fi)) >= 0) {
345  rpmuint32_t dil;
346  size_t dnlen, bnlen;
347 
348  if (!S_ISDIR(fi->fmodes[i]))
349  continue;
350 
351  dil = fi->dil[i];
352  dnlen = strlen(fi->dnl[dil]);
353  bnlen = strlen(fi->bnl[i]);
354 
355  for (j = 0; j < (int)fi->dc; j++) {
356  size_t jlen;
357 
358  if (!dnli->active[j] || j == (int)dil)
359  /*@innercontinue@*/ continue;
360  (void) urlPath(fi->dnl[j], &dnl);
361  jlen = strlen(dnl);
362  if (jlen != (dnlen+bnlen+1))
363  /*@innercontinue@*/ continue;
364  if (strncmp(dnl, fi->dnl[dil], dnlen))
365  /*@innercontinue@*/ continue;
366  if (strncmp(dnl+dnlen, fi->bnl[i], bnlen))
367  /*@innercontinue@*/ continue;
368  if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
369  /*@innercontinue@*/ continue;
370  /* This directory is included in the package. */
371  dnli->active[j] = 0;
372  /*@innerbreak@*/ break;
373  }
374  }
375 
376  /* Print only once per package. */
377  if (!reverse) {
378  j = 0;
379  for (i = 0; i < (int)fi->dc; i++) {
380  if (!dnli->active[i]) continue;
381  if (j == 0) {
382  j = 1;
384  D_("========== Directories not explicitly included in package:\n"));
385  }
386  (void) urlPath(fi->dnl[i], &dnl);
387  rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, dnl);
388  }
389  if (j)
390  rpmlog(RPMLOG_DEBUG, "==========\n");
391  }
392  }
393  return dnli;
394 }
395 /*@=usereleased@*/
396 
402 static /*@observer@*/ /*@null@*/
403 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli)
404  /*@modifies dnli @*/
405 {
406  const char * dn = NULL;
407 
408  if (dnli) {
409  rpmfi fi = dnli->fi;
410  int i = -1;
411 
412  if (dnli->active)
413  do {
414  i = (!dnli->reverse ? dnli->i++ : --dnli->i);
415  } while (i >= 0 && i < (int)fi->dc && !dnli->active[i]);
416 
417  if (i >= 0 && i < (int)fi->dc)
418  dn = fi->dnl[i];
419  else
420  i = -1;
421  dnli->isave = i;
422  }
423  return dn;
424 }
425 
426 #if defined(WITH_PTHREADS)
427 static void * fsmThread(void * _fsm)
428  /*@globals h_errno, fileSystem, internalState @*/
429  /*@modifies arg, fileSystem, internalState @*/
430 {
431  IOSM_t fsm = (IOSM_t) _fsm;
432 /*@-unqualifiedtrans@*/
433  return ((void *) ((long)fsmStage(fsm, fsm->nstage)));
434 /*@=unqualifiedtrans@*/
435 }
436 #endif
437 
438 int fsmNext(IOSM_t fsm, iosmFileStage nstage)
439  /*@globals h_errno, fileSystem, internalState @*/
440  /*@modifies fsm, fileSystem, internalState @*/
441 {
442  fsm->nstage = nstage;
443 #if defined(WITH_PTHREADS)
444  if (fsm->multithreaded)
445  return rpmsqJoin( rpmsqThread(fsmThread, fsm) );
446 #endif
447  return fsmStage(fsm, fsm->nstage);
448 }
449 
455 static int saveHardLink(/*@special@*/ /*@partial@*/ IOSM_t fsm)
456  /*@uses fsm->links, fsm->ix, fsm->sb, fsm->goal, fsm->nsuffix @*/
457  /*@defines fsm->li @*/
458  /*@releases fsm->path @*/
459  /*@globals h_errno, fileSystem, internalState @*/
460  /*@modifies fsm, fileSystem, internalState @*/
461 {
462  struct stat * st = &fsm->sb;
463  int rc = 0;
464  int ix = -1;
465  int j;
466 
467  /* Find hard link set. */
468  for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
469  if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
470  break;
471  }
472 
473  /* New hard link encountered, add new link to set. */
474  if (fsm->li == NULL) {
475  fsm->li = (struct hardLink_s *) xcalloc(1, sizeof(*fsm->li));
476  fsm->li->next = NULL;
477  fsm->li->sb = *st; /* structure assignment */
478  fsm->li->nlink = (int) st->st_nlink;
479  fsm->li->linkIndex = fsm->ix;
480  fsm->li->createdPath = -1;
481 
482  fsm->li->filex = (int *) xcalloc(st->st_nlink, sizeof(fsm->li->filex[0]));
483  memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0])));
484  fsm->li->nsuffix = (const char **) xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix));
485 
486  if (fsm->goal == IOSM_PKGBUILD)
487  fsm->li->linksLeft = (int) st->st_nlink;
488  if (fsm->goal == IOSM_PKGINSTALL)
489  fsm->li->linksLeft = 0;
490 
491  /*@-kepttrans@*/
492  fsm->li->next = fsm->links;
493  /*@=kepttrans@*/
494  fsm->links = fsm->li;
495  }
496 
497  if (fsm->goal == IOSM_PKGBUILD) --fsm->li->linksLeft;
498  fsm->li->filex[fsm->li->linksLeft] = fsm->ix;
499  /*@-observertrans -dependenttrans@*/
500  fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix;
501  /*@=observertrans =dependenttrans@*/
502  if (fsm->goal == IOSM_PKGINSTALL) fsm->li->linksLeft++;
503 
504  if (fsm->goal == IOSM_PKGBUILD)
505  return (fsm->li->linksLeft > 0);
506 
507  if (fsm->goal != IOSM_PKGINSTALL)
508  return 0;
509 
510  if (!(st->st_size || fsm->li->linksLeft == (int) st->st_nlink))
511  return 1;
512 
513  /* Here come the bits, time to choose a non-skipped file name. */
514  { rpmfi fi = fsmGetFi(fsm);
515 
516  for (j = fsm->li->linksLeft - 1; j >= 0; j--) {
517  ix = fsm->li->filex[j];
518  if (ix < 0 || iosmFileActionSkipped(fi->actions[ix]))
519  continue;
520  break;
521  }
522  }
523 
524  /* Are all links skipped or not encountered yet? */
525  if (ix < 0 || j < 0)
526  return 1; /* XXX W2DO? */
527 
528  /* Save the non-skipped file name and map index. */
529  fsm->li->linkIndex = j;
530  fsm->path = _free(fsm->path);
531  fsm->ix = ix;
532  rc = fsmNext(fsm, IOSM_MAP);
533  return rc;
534 }
535 
541 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li)
542  /*@modifies li @*/
543 {
544  if (li) {
545  li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */
546  li->filex = _free(li->filex);
547  }
548  return _free(li);
549 }
550 
552 {
553  IOSM_t fsm = (IOSM_t) xcalloc(1, sizeof(*fsm));
554  return fsm;
555 }
556 
558 {
559  if (fsm) {
560  fsm->path = _free(fsm->path);
561  while ((fsm->li = fsm->links) != NULL) {
562  fsm->links = fsm->li->next;
563  fsm->li->next = NULL;
564  fsm->li = freeHardLink((struct hardLink_s *)fsm->li);
565  }
566  fsm->dnlx = _free(fsm->dnlx);
567  fsm->ldn = _free(fsm->ldn);
568  fsm->iter = mapFreeIterator(fsm->iter);
569  }
570  return _free(fsm);
571 }
572 
573 #if defined(SUPPORT_AR_PAYLOADS)
574 static int arSetup(IOSM_t fsm, rpmfi fi)
575  /*@modifies fsm @*/
576 {
577  const char * path;
578  char * t;
579  size_t lmtablen = 0;
580  size_t nb;
581 
582  /* Calculate size of ar(1) long member table. */
583  if ((fi = rpmfiInit(fi, 0)) != NULL)
584  while (rpmfiNext(fi) >= 0) {
585 #ifdef NOTYET
586  if (fi->apath) {
587  const char * apath = NULL;
588  (void) urlPath(fi->apath[ix], &apath);
589  path = apath + fi->striplen;
590  } else
591 #endif
592  path = rpmfiBN(fi);
593  if ((nb = strlen(path)) < 15)
594  continue;
595  lmtablen += nb + 1; /* trailing \n */
596  }
597 
598  /* Anything to do? */
599  if (lmtablen == 0)
600  return 0;
601 
602  /* Create and load ar(1) long member table. */
603  fsm->lmtab = t = (char *) xmalloc(lmtablen + 1); /* trailing \0 */
604  fsm->lmtablen = lmtablen;
605  fsm->lmtaboff = 0;
606  if ((fi = rpmfiInit(fi, 0)) != NULL)
607  while (rpmfiNext(fi) >= 0) {
608 #ifdef NOTYET
609  if (fi->apath) {
610  const char * apath = NULL;
611  (void) urlPath(fi->apath[ix], &apath);
612  path = apath + fi->striplen;
613  } else
614 #endif
615  path = rpmfiBN(fi);
616  if ((nb = strlen(path)) < 15)
617  continue;
618  t = stpcpy(t, path);
619  *t++ = '\n';
620  }
621  *t = '\0';
622 
623  return 0;
624 }
625 #endif
626 
627 int fsmSetup(void * _fsm, iosmFileStage goal, const char * afmt,
628  const void * _ts, const void * _fi, FD_t cfd,
629  unsigned int * archiveSize, const char ** failedFile)
630 {
631  IOSM_t fsm = (IOSM_t) _fsm;
632 /*@-castexpose@*/
633  const rpmts ts = (const rpmts) _ts;
634  const rpmfi fi = (const rpmfi) _fi;
635 /*@=castexpose@*/
636 #if defined(_USE_RPMTE)
637  int reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT);
638  int adding = (rpmteType(fi->te) == TR_ADDED);
639 #else
640  int reverse = 0; /* XXX HACK: devise alternative means */
641  int adding = 1; /* XXX HACK: devise alternative means */
642 #endif
643  size_t pos = 0;
644  int rc, ec = 0;
645 
646  fsm->debug = _fsm_debug;
648  fsm->adding = adding;
649 
650 /*@+voidabstract -nullpass@*/
651 if (fsm->debug < 0)
652 fprintf(stderr, "--> fsmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", fsm, goal, afmt, (void *)ts, fi, cfd, archiveSize, failedFile);
653 /*@=voidabstract =nullpass@*/
654 
655  _iosmNext = &fsmNext;
656  if (fsm->headerRead == NULL) {
657  if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) {
658 if (fsm->debug < 0)
659 fprintf(stderr, "\ttar vectors set\n");
660  fsm->headerRead = &tarHeaderRead;
661  fsm->headerWrite = &tarHeaderWrite;
663  fsm->blksize = TAR_BLOCK_SIZE;
664  } else
665 #if defined(SUPPORT_AR_PAYLOADS)
666  if (afmt != NULL && !strcmp(afmt, "ar")) {
667 if (fsm->debug < 0)
668 fprintf(stderr, "\tar vectors set\n");
669  fsm->headerRead = &arHeaderRead;
670  fsm->headerWrite = &arHeaderWrite;
672  fsm->blksize = 2;
673  if (goal == IOSM_PKGBUILD || goal == IOSM_PKGERASE)
674  (void) arSetup(fsm, fi);
675  } else
676 #endif
677  {
678 if (fsm->debug < 0)
679 fprintf(stderr, "\tcpio vectors set\n");
680  fsm->headerRead = &cpioHeaderRead;
683  fsm->blksize = 4;
684  }
685  }
686 
687  fsm->goal = goal;
688  if (cfd != NULL) {
689 /*@-assignexpose -castexpose @*/
690  fsm->cfd = fdLink(cfd, "persist (fsm)");
691 /*@=assignexpose =castexpose @*/
692  pos = fdGetCpioPos(fsm->cfd);
693  fdSetCpioPos(fsm->cfd, 0);
694  }
695 /*@-mods@*/ /* LCL: avoid void * _ts/_fi annotations for now. */
696  fsm->iter = mapInitIterator(fi, reverse);
697 /*@-assignexpose -castexpose @*/
698  fsm->iter->ts = rpmtsLink(ts, "mapIterator");
699 /*@=assignexpose =castexpose @*/
701 /*@=mods@*/
702  fsm->nofdigests =
703  (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS))
704  ? 0 : 1;
705 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
706  fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) &&
707  fsm->goal != IOSM_PKGCOMMIT) ? 0 : 1);
708 #undef _tsmask
709 
710  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
711  void * ptr;
712  fi->archivePos = 0;
713  ptr = rpmtsNotify(ts, fi->te,
714  RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize);
715  }
716 
717  /*@-assignexpose@*/
718  fsm->archiveSize = archiveSize;
719  if (fsm->archiveSize)
720  *fsm->archiveSize = 0;
721  fsm->failedFile = failedFile;
722  if (fsm->failedFile)
723  *fsm->failedFile = NULL;
724  /*@=assignexpose@*/
725 
726  memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf));
727  if (fsm->goal == IOSM_PKGINSTALL) {
728  if (ts && rpmtsGetTid(ts) != (rpmuint32_t)-1)
729  sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts));
730  }
731 
732  ec = fsm->rc = 0;
733 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */
734  rc = fsmUNSAFE(fsm, IOSM_CREATE);
735 /*@=mods@*/
736  if (rc && !ec) ec = rc;
737 
738 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */
739  rc = fsmUNSAFE(fsm, fsm->goal);
740 /*@=mods@*/
741  if (rc && !ec) ec = rc;
742 
743  if (fsm->archiveSize && ec == 0)
744  *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos);
745 
746 /*@-nullstate@*/ /* FIX: *fsm->failedFile may be NULL */
747  return ec;
748 /*@=nullstate@*/
749 }
750 
751 int fsmTeardown(void * _fsm)
752 {
753  IOSM_t fsm = (IOSM_t) _fsm;
754  int rc = fsm->rc;
755 
756 if (fsm->debug < 0)
757 fprintf(stderr, "--> fsmTeardown(%p)\n", fsm);
758  if (!rc)
759  rc = fsmUNSAFE(fsm, IOSM_DESTROY);
760 
762  &fsm->op_digest);
763 
764  fsm->lmtab = _free(fsm->lmtab);
765  (void)rpmtsFree(fsm->iter->ts);
766  fsm->iter->ts = NULL;
767  fsm->iter = mapFreeIterator(fsm->iter);
768  if (fsm->cfd != NULL) {
769 /*@-refcounttrans@*/ /* FIX: XfdFree annotation */
770  fsm->cfd = fdFree(fsm->cfd, "persist (fsm)");
771 /*@=refcounttrans@*/
772  fsm->cfd = NULL;
773  }
774  fsm->failedFile = NULL;
775  return rc;
776 }
777 
778 /*
779  * Set file security context (if not disabled).
780  * @param fsm file state machine data
781  * @return 0 always
782  */
783 static int fsmMapFContext(IOSM_t fsm)
784  /*@modifies fsm @*/
785 {
786  fsm->fcontext = NULL;
787  if (!fsm->nofcontexts) {
788  fsm->fcontext = rpmsxMatch(NULL, fsm->path, fsm->sb.st_mode);
789 #ifdef DYING /* XXX SELinux file contexts not set from package content. */
790  { rpmfi fi = fsmGetFi(fsm);
791  int i = fsm->ix;
792 
793  /* Get file security context from package. */
794  if (fi && i >= 0 && i < (int)fi->fc)
795  fsm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL);
796  }
797 #endif
798  }
799  return 0;
800 }
801 
803 {
804  rpmfi fi = fsmGetFi(fsm); /* XXX const except for fstates */
805  int teAdding = fsm->adding;
806  int rc = 0;
807  int i = fsm->ix;
808 
809 assert(fi); /* XXX coverity #1035927 */
810  fsm->osuffix = NULL;
811  fsm->nsuffix = NULL;
812  fsm->astriplen = 0;
813  fsm->action = FA_UNKNOWN;
814  fsm->mapFlags = fi->mapflags;
815 
816  if (i >= 0 && i < (int)fi->fc) {
817 
818  fsm->astriplen = fi->astriplen;
819  fsm->action = (fi->actions ? fi->actions[i] : fi->action);
820  fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags);
821  fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
822 
823  /* src rpms have simple base name in payload. */
824  fsm->dirName = fi->dnl[fi->dil[i]];
825  fsm->baseName = fi->bnl[i];
826 
827  switch (fsm->action) {
828  case FA_SKIP:
829  break;
830  case FA_UNKNOWN:
831  break;
832 
833  case FA_COPYOUT:
834  break;
835  case FA_COPYIN:
836  case FA_CREATE:
837 assert(teAdding);
838  break;
839 
840  case FA_SKIPNSTATE:
841  if (fi->fstates && teAdding)
842  fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED;
843  break;
844 
845  case FA_SKIPNETSHARED:
846  if (fi->fstates && teAdding)
847  fi->fstates[i] = RPMFILE_STATE_NETSHARED;
848  break;
849 
850  case FA_SKIPCOLOR:
851  if (fi->fstates && teAdding)
852  fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR;
853  break;
854 
855  case FA_BACKUP:
856  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
857  fsm->osuffix = (teAdding ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE);
858  break;
859 
860  case FA_ALTNAME:
861 assert(teAdding);
862  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
863  fsm->nsuffix = SUFFIX_RPMNEW;
864  break;
865 
866  case FA_SAVE:
867 assert(teAdding);
868  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
869  fsm->osuffix = SUFFIX_RPMSAVE;
870  break;
871  case FA_ERASE:
872 #if 0 /* XXX is this a genhdlist fix? */
873  assert(rpmteType(fi->te) == TR_REMOVED);
874 #endif
875  /*
876  * XXX TODO: %ghost probably shouldn't be removed, but that changes
877  * legacy rpm behavior.
878  */
879  break;
880  default:
881  break;
882  }
883 
884  if ((fsm->mapFlags & IOSM_MAP_PATH) || fsm->nsuffix) {
885  const struct stat * st = &fsm->sb;
886  fsm->path = _free(fsm->path);
887  fsm->path = fsmFsPath(fsm, st, fsm->subdir,
888  (fsm->suffix ? fsm->suffix : fsm->nsuffix));
889  }
890  }
891  return rc;
892 }
893 
895 {
896  struct stat * st = &fsm->sb;
897  rpmfi fi = fsmGetFi(fsm);
898  int i = fsm->ix;
899 
900  if (fi && i >= 0 && i < (int) fi->fc) {
901  mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
902  mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms);
903  ino_t finalInode = (fi->finodes ? (ino_t)fi->finodes[i] : 0);
904  dev_t finalRdev = (dev_t)(fi->frdevs ? fi->frdevs[i] : 0);
905  rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
906  uid_t uid = fi->uid;
907  gid_t gid = fi->gid;
908 
909  /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during
910  installation of _source_ RPMs. Instead, let it use the current
911  run-time owner/group, because most of the time the owner/group in
912  the source RPM (which is the owner/group of the files as staying on
913  the package author system) is not existing on the target system, of
914  course. */
915  if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
916  if (!fi->isSource) {
917  if (fsm->goal == IOSM_PKGINSTALL)
919  _("user %s does not exist - using root\n"), fi->fuser[i]);
920  uid = 0;
921  finalMode &= ~S_ISUID; /* turn off suid bit */
922  }
923  }
924 
925  if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
926  if (!fi->isSource) {
927  if (fsm->goal == IOSM_PKGINSTALL)
929  _("group %s does not exist - using root\n"), fi->fgroup[i]);
930  gid = 0;
931  finalMode &= ~S_ISGID; /* turn off sgid bit */
932  }
933  }
934 
935  if (fsm->mapFlags & IOSM_MAP_MODE)
936  st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
937  if (fsm->mapFlags & IOSM_MAP_TYPE) {
938  st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
939  if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
940  && st->st_nlink == 0)
941  st->st_nlink = 1;
942  st->st_rdev = finalRdev;
943  st->st_ino = finalInode;
944  st->st_mtime = finalMtime;
945  }
946  if (fsm->mapFlags & IOSM_MAP_UID)
947  st->st_uid = uid;
948  if (fsm->mapFlags & IOSM_MAP_GID)
949  st->st_gid = gid;
950 
951  /*
952  * Set file digest (if not disabled).
953  */
954  if (!fsm->nofdigests) {
955  fsm->fdigestalgo = fi->digestalgo;
956  fsm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL);
957  fsm->digestlen = fi->digestlen;
958  fsm->digest = (fi->digests ? (fi->digests + (fsm->digestlen * i)) : NULL);
959  } else {
960  fsm->fdigestalgo = 0;
961  fsm->fdigest = NULL;
962  fsm->digestlen = 0;
963  fsm->digest = NULL;
964  }
965  }
966  return 0;
967 }
968 
974 /*@-compdef@*/
975 static int extractRegular(/*@special@*/ IOSM_t fsm)
976  /*@uses fsm->fdigest, fsm->digest, fsm->sb, fsm->wfd @*/
977  /*@globals h_errno, fileSystem, internalState @*/
978  /*@modifies fsm, fileSystem, internalState @*/
979 {
980  const struct stat * st = &fsm->sb;
981  size_t left = (size_t) st->st_size;
982  int rc = 0;
983  int xx;
984 
985  { const char * fn = fsm->path;
986  mode_t mode = st->st_mode;
987  uint8_t * b = (uint8_t *)"";
988  size_t blen = 1;
989  const uint8_t * d = fsm->digest;
990  size_t dlen = fsm->digestlen;
991  uint32_t dalgo = fsm->fdigestalgo;
992 
993  xx = rpmlioCreat(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo);
994  }
995 
996  rc = fsmNext(fsm, IOSM_WOPEN);
997  if (rc)
998  goto exit;
999 
1000  if (st->st_size > 0 && (fsm->fdigest != NULL || fsm->digest != NULL))
1001  fdInitDigest(fsm->wfd, fsm->fdigestalgo, 0);
1002 
1003  while (left) {
1004 
1005  fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
1006  rc = fsmNext(fsm, IOSM_DREAD);
1007  if (rc)
1008  goto exit;
1009 
1010  rc = fsmNext(fsm, IOSM_WRITE);
1011  if (rc)
1012  goto exit;
1013 
1014  left -= fsm->wrnb;
1015 
1016  /* Notify iff progress, completion is done elsewhere */
1017  if (!rc && left)
1018  (void) fsmNext(fsm, IOSM_NOTIFY);
1019  }
1020 
1021 #ifdef DYING
1022 /* Measurements from installing kernel-source package:
1023  * +fsync
1024  * total: 1 0.000000 MB 640.854524 secs
1025  * +fdatasync
1026  * total: 1 0.000000 MB 419.983200 secs
1027  * w/o fsync/fdsatasync:
1028  * total: 1 0.000000 MB 12.492918 secs
1029  */
1030  xx = fsync(Fileno(fsm->wfd));
1031 #endif
1032 
1033  if (st->st_size > 0 && (fsm->fdigest || fsm->digest)) {
1034  void * digest = NULL;
1035  int asAscii = (fsm->digest == NULL ? 1 : 0);
1036 
1037  (void) Fflush(fsm->wfd);
1038  fdFiniDigest(fsm->wfd, fsm->fdigestalgo, &digest, NULL, asAscii);
1039 
1040  if (digest == NULL) {
1042  goto exit;
1043  }
1044 
1045  if (fsm->digest != NULL) {
1046  if (memcmp(digest, fsm->digest, fsm->digestlen))
1048  } else {
1049  if (strcmp(digest, fsm->fdigest))
1051  }
1052  digest = _free(digest);
1053  }
1054 
1055 exit:
1056  (void) fsmNext(fsm, IOSM_WCLOSE);
1057 
1058  return rc;
1059 }
1060 /*@=compdef@*/
1061 
1068 /*@-compdef -compmempass@*/
1069 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t fsm, int writeData)
1070  /*@uses fsm->path, fsm->opath, fsm->sb, fsm->osb, fsm->cfd @*/
1071  /*@globals h_errno, fileSystem, internalState @*/
1072  /*@modifies fsm, fileSystem, internalState @*/
1073 {
1074  const char * path = fsm->path;
1075  const char * opath = fsm->opath;
1076  struct stat * st = &fsm->sb;
1077  struct stat * ost = &fsm->osb;
1078  size_t left;
1079  int xx;
1080  int rc;
1081 
1082  st->st_size = (writeData ? ost->st_size : 0);
1083 
1084  if (S_ISDIR(st->st_mode)) {
1085  st->st_size = 0;
1086  } else if (S_ISLNK(st->st_mode)) {
1087  /*
1088  * While linux puts the size of a symlink in the st_size field,
1089  * I don't think that's a specified standard.
1090  */
1091  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
1092  rc = fsmUNSAFE(fsm, IOSM_READLINK);
1093  if (rc) goto exit;
1094  st->st_size = fsm->rdnb;
1095  fsm->lpath = xstrdup(fsm->rdbuf); /* XXX save readlink return. */
1096  }
1097 
1098  if (fsm->mapFlags & IOSM_MAP_ABSOLUTE) {
1099  size_t nb= strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof(".");
1100  char * t = (char *) alloca(nb);
1101  *t = '\0';
1102  fsm->path = t;
1103  if (fsm->mapFlags & IOSM_MAP_ADDDOT)
1104  *t++ = '.';
1105  t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName);
1106  } else if (fsm->mapFlags & IOSM_MAP_PATH) {
1107  rpmfi fi = fsmGetFi(fsm);
1108  if (fi->apath) {
1109  const char * apath = NULL;
1110  (void) urlPath(fi->apath[fsm->ix], &apath);
1111  fsm->path = apath + fi->striplen;
1112  } else
1113  fsm->path = fi->bnl[fsm->ix];
1114  }
1115 
1116  rc = fsmNext(fsm, IOSM_HWRITE);
1117  fsm->path = path;
1118  if (rc) goto exit;
1119 
1120  if (writeData && S_ISREG(st->st_mode)) {
1121 #if defined(HAVE_MMAP)
1122  char * rdbuf = NULL;
1123  void * mapped = (void *)-1;
1124  size_t nmapped = 0;
1125  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */
1126  int use_mmap = (st->st_size <= 0x07ffffff);
1127 #endif
1128 
1129  rc = fsmNext(fsm, IOSM_ROPEN);
1130  if (rc) goto exit;
1131 
1132  /* XXX unbuffered mmap generates *lots* of fdio debugging */
1133 #if defined(HAVE_MMAP)
1134  if (use_mmap) {
1135  mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0);
1136  if (mapped != (void *)-1) {
1137  rdbuf = fsm->rdbuf;
1138  fsm->rdbuf = (char *) mapped;
1139  fsm->rdlen = nmapped = st->st_size;
1140 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1141  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1142 #endif
1143  }
1144  }
1145 #endif
1146 
1147  left = st->st_size;
1148 
1149  while (left) {
1150 #if defined(HAVE_MMAP)
1151  if (mapped != (void *)-1) {
1152  fsm->rdnb = nmapped;
1153  } else
1154 #endif
1155  {
1156  fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
1157  rc = fsmNext(fsm, IOSM_READ);
1158  if (rc) goto exit;
1159  }
1160 
1161  /* XXX DWRITE uses rdnb for I/O length. */
1162  rc = fsmNext(fsm, IOSM_DWRITE);
1163  if (rc) goto exit;
1164 
1165  left -= fsm->wrnb;
1166  }
1167 
1168 #if defined(HAVE_MMAP)
1169  if (mapped != (void *)-1) {
1170 /* XXX splint misses size_t 2nd arg. */
1171 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC);
1172 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1173  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1174 #endif
1175  xx = munmap(mapped, nmapped);
1176  fsm->rdbuf = rdbuf;
1177  } else
1178 #endif
1179  { int fdno = Fileno(fsm->rfd);
1180  if (fdno >= 0)
1181  xx = fsync(fdno); /* XXX coverity #1035827 */
1182  }
1183  }
1184 
1185  rc = fsmNext(fsm, IOSM_PAD);
1186  if (rc) goto exit;
1187 
1188  rc = 0;
1189 
1190 exit:
1191  if (fsm->rfd != NULL)
1192  (void) fsmNext(fsm, IOSM_RCLOSE);
1193 /*@-dependenttrans@*/
1194  fsm->opath = opath;
1195  fsm->path = path;
1196 /*@=dependenttrans@*/
1197  return rc;
1198 }
1199 /*@=compdef =compmempass@*/
1200 
1206 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1207  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->li, fsm->failedFile @*/
1208  /*@globals h_errno, fileSystem, internalState @*/
1209  /*@modifies fsm, fileSystem, internalState @*/
1210 {
1211  const char * path = fsm->path;
1212  const char * lpath = fsm->lpath;
1213  const char * nsuffix = fsm->nsuffix;
1214  int iterIndex = fsm->ix;
1215  int ec = 0;
1216  int rc;
1217  int i;
1218  const char * linkpath = NULL;
1219  int firstfile = 1;
1220 
1221  fsm->path = NULL;
1222  fsm->lpath = NULL;
1223  fsm->nsuffix = NULL;
1224  fsm->ix = -1;
1225 
1226  for (i = fsm->li->nlink - 1; i >= 0; i--) {
1227 
1228  if (fsm->li->filex[i] < 0) continue;
1229 
1230  fsm->ix = fsm->li->filex[i];
1231 /*@-compdef@*/
1232  rc = fsmNext(fsm, IOSM_MAP);
1233 /*@=compdef@*/
1234 
1235  /* XXX tar and cpio have to do things differently. */
1236  if (fsm->headerWrite == tarHeaderWrite) {
1237  if (firstfile) {
1238  const char * apath = NULL;
1239  char *t;
1240  (void) urlPath(fsm->path, &apath);
1241  /* Remove the buildroot prefix. */
1242  t = (char *) xmalloc(sizeof(".") + strlen(apath + fsm->astriplen));
1243  (void) stpcpy( stpcpy(t, "."), apath + fsm->astriplen);
1244  linkpath = t;
1245  firstfile = 0;
1246  } else
1247  fsm->lpath = linkpath;
1248 
1249  /* Write data after first link for tar. */
1250  rc = writeFile(fsm, (fsm->lpath == NULL));
1251  } else {
1252  /* Write data after last link for cpio. */
1253  rc = writeFile(fsm, (i == 0));
1254  }
1255  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1256  ec = rc;
1257  *fsm->failedFile = xstrdup(fsm->path);
1258  }
1259 
1260  fsm->path = _free(fsm->path);
1261  fsm->li->filex[i] = -1;
1262  }
1263 
1264 /*@-dependenttrans@*/
1265  linkpath = _free(linkpath);
1266 /*@=dependenttrans@*/
1267  fsm->ix = iterIndex;
1268  fsm->nsuffix = nsuffix;
1269  fsm->lpath = lpath;
1270  fsm->path = path;
1271  return ec;
1272 }
1273 
1279 /*@-compdef@*/
1280 static int fsmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1281  /*@uses fsm->path, fsm->opath, fsm->nsuffix, fsm->ix, fsm->li @*/
1282  /*@globals h_errno, fileSystem, internalState @*/
1283  /*@modifies fsm, fileSystem, internalState @*/
1284 {
1285  const char * path = fsm->path;
1286  const char * opath = fsm->opath;
1287  const char * nsuffix = fsm->nsuffix;
1288  int iterIndex = fsm->ix;
1289  int ec = 0;
1290  int rc;
1291  int i;
1292 
1293  fsm->path = NULL;
1294  fsm->opath = NULL;
1295  fsm->nsuffix = NULL;
1296  fsm->ix = -1;
1297 
1298  fsm->ix = fsm->li->filex[fsm->li->createdPath];
1299  rc = fsmNext(fsm, IOSM_MAP);
1300  fsm->opath = fsm->path;
1301  fsm->path = NULL;
1302  for (i = 0; i < fsm->li->nlink; i++) {
1303  if (fsm->li->filex[i] < 0) continue;
1304  if (fsm->li->createdPath == i) continue;
1305 
1306  fsm->ix = fsm->li->filex[i];
1307  fsm->path = _free(fsm->path);
1308  rc = fsmNext(fsm, IOSM_MAP);
1309  if (iosmFileActionSkipped(fsm->action)) continue;
1310 
1311  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1312  if (!rc) continue;
1313  if (!(rc == IOSMERR_ENOENT)) break;
1314 
1315  /* XXX link(fsm->opath, fsm->path) */
1316  rc = fsmNext(fsm, IOSM_LINK);
1317  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1318  ec = rc;
1319  *fsm->failedFile = xstrdup(fsm->path);
1320  }
1321 
1322  fsm->li->linksLeft--;
1323  }
1324  fsm->path = _free(fsm->path);
1325  fsm->opath = _free(fsm->opath);
1326 
1327  fsm->ix = iterIndex;
1328  fsm->nsuffix = nsuffix;
1329  fsm->path = path;
1330  fsm->opath = opath;
1331  return ec;
1332 }
1333 /*@=compdef@*/
1334 
1340 /*@-compdef@*/
1341 static int fsmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1342  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->sb,
1343  fsm->li, fsm->links @*/
1344  /*@globals h_errno, fileSystem, internalState @*/
1345  /*@modifies fsm, fileSystem, internalState @*/
1346 {
1347  const char * path = fsm->path;
1348  const char * nsuffix = fsm->nsuffix;
1349  int iterIndex = fsm->ix;
1350  struct stat * st = &fsm->sb;
1351  int rc = 0;
1352  int i;
1353 
1354  fsm->path = NULL;
1355  fsm->nsuffix = NULL;
1356  fsm->ix = -1;
1357 
1358  for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
1359  if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
1360  break;
1361  }
1362 
1363 assert(fsm->li); /* XXX coverity #1035780 */
1364  for (i = 0; i < fsm->li->nlink; i++) {
1365  if (fsm->li->filex[i] < 0) continue;
1366  fsm->ix = fsm->li->filex[i];
1367  rc = fsmNext(fsm, IOSM_MAP);
1368  if (!iosmFileActionSkipped(fsm->action))
1369  rc = fsmNext(fsm, IOSM_COMMIT);
1370  fsm->path = _free(fsm->path);
1371  fsm->li->filex[i] = -1;
1372  }
1373 
1374  fsm->ix = iterIndex;
1375  fsm->nsuffix = nsuffix;
1376  fsm->path = path;
1377  return rc;
1378 }
1379 /*@=compdef@*/
1380 
1386 static int fsmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1387  /*@uses fsm->path, fsm->dnlx, fsm->ldn, fsm->rdbuf, fsm->iter @*/
1388  /*@globals h_errno, fileSystem, internalState @*/
1389  /*@modifies fsm, fileSystem, internalState @*/
1390 {
1391  const char * path = fsm->path;
1392  void * dnli = dnlInitIterator(fsm, 1);
1393  char * dn = fsm->rdbuf;
1394  int dc = dnlCount(dnli);
1395  int rc = 0;
1396 
1397  fsm->path = NULL;
1398  dn[0] = '\0';
1399  /*@-observertrans -dependenttrans@*/
1400  if (fsm->ldn != NULL && fsm->dnlx != NULL)
1401  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1402  size_t dnlen = strlen(fsm->path);
1403  char * te;
1404 
1405  dc = dnlIndex(dnli);
1406  if (fsm->dnlx[dc] < 1 || (size_t)fsm->dnlx[dc] >= dnlen)
1407  continue;
1408 
1409  /* Copy to avoid const on fsm->path. */
1410  te = stpcpy(dn, fsm->path) - 1;
1411  fsm->path = dn;
1412 
1413  /* Remove generated directories. */
1414  /*@-usereleased@*/ /* LCL: te used after release? */
1415  do {
1416  if (*te == '/') {
1417  *te = '\0';
1418 /*@-compdef@*/
1419  rc = fsmNext(fsm, IOSM_RMDIR);
1420 /*@=compdef@*/
1421  *te = '/';
1422  }
1423  if (rc)
1424  /*@innerbreak@*/ break;
1425  te--;
1426  } while ((te - fsm->path) > fsm->dnlx[dc]);
1427  /*@=usereleased@*/
1428  }
1429  dnli = dnlFreeIterator(dnli);
1430  /*@=observertrans =dependenttrans@*/
1431 
1432  fsm->path = path;
1433  return rc;
1434 }
1435 
1441 static int fsmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1442  /*@uses fsm->path, fsm->sb, fsm->osb, fsm->rdbuf, fsm->iter,
1443  fsm->ldn, fsm->ldnlen, fsm->ldnalloc @*/
1444  /*@defines fsm->dnlx, fsm->ldn @*/
1445  /*@globals h_errno, fileSystem, internalState @*/
1446  /*@modifies fsm, fileSystem, internalState @*/
1447 {
1448  struct stat * st = &fsm->sb;
1449  struct stat * ost = &fsm->osb;
1450  const char * path = fsm->path;
1451  mode_t st_mode = st->st_mode;
1452  void * dnli = dnlInitIterator(fsm, 0);
1453  char * dn = fsm->rdbuf;
1454  int dc = dnlCount(dnli);
1455  int rc = 0;
1456  size_t i;
1457 
1458  fsm->path = NULL;
1459 
1460  dn[0] = '\0';
1461  fsm->dnlx = (unsigned short *) (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL);
1462  /*@-observertrans -dependenttrans@*/
1463  if (fsm->dnlx != NULL)
1464  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1465  size_t dnlen = strlen(fsm->path);
1466  char * te;
1467 
1468  dc = dnlIndex(dnli);
1469  if (dc < 0) continue;
1470  fsm->dnlx[dc] = (unsigned short) dnlen;
1471  if (dnlen <= 1)
1472  continue;
1473 
1474  /*@-compdef -nullpass@*/ /* FIX: fsm->ldn not defined ??? */
1475  if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn))
1476  continue;
1477  /*@=compdef =nullpass@*/
1478 
1479  /* Copy to avoid const on fsm->path. */
1480  (void) stpcpy(dn, fsm->path);
1481  fsm->path = dn;
1482 
1483  /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
1484  (void) urlPath(dn, (const char **)&te);
1485  for (i = 1, te++; *te != '\0'; te++, i++) {
1486  if (*te != '/')
1487  /*@innercontinue@*/ continue;
1488 
1489  *te = '\0';
1490 
1491  /* Already validated? */
1492  /*@-usedef -compdef -nullpass -nullderef@*/
1493  if (i < fsm->ldnlen &&
1494  (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') &&
1495  !strncmp(fsm->path, fsm->ldn, i))
1496  {
1497  *te = '/';
1498  /* Move pre-existing path marker forward. */
1499  fsm->dnlx[dc] = (te - dn);
1500  /*@innercontinue@*/ continue;
1501  }
1502  /*@=usedef =compdef =nullpass =nullderef@*/
1503 
1504  /* Validate next component of path. */
1505  rc = fsmUNSAFE(fsm, IOSM_LSTAT);
1506  *te = '/';
1507 
1508  /* Directory already exists? */
1509  if (rc == 0 && S_ISDIR(ost->st_mode)) {
1510  /* Move pre-existing path marker forward. */
1511  fsm->dnlx[dc] = (te - dn);
1512  } else if (rc == IOSMERR_ENOENT) {
1513  rpmfi fi = fsmGetFi(fsm);
1514  *te = '\0';
1515  st->st_mode = S_IFDIR | (fi->dperms & 07777);
1516  rc = fsmNext(fsm, IOSM_MKDIR);
1517  if (!rc) {
1518  /* XXX FIXME? only new dir will have context set. */
1519  /* Get file security context from patterns. */
1520  if (!fsm->nofcontexts) {
1521  fsm->fcontext =
1522  rpmsxMatch(NULL, fsm->path, st->st_mode);
1523  if (fsm->fcontext != NULL)
1524  rc = fsmNext(fsm, IOSM_LSETFCON);
1525  } else
1526  fsm->fcontext = NULL;
1528  D_("%s directory created with perms %04o, context %s.\n"),
1529  fsm->path, (unsigned)(st->st_mode & 07777),
1530  (fsm->fcontext ? fsm->fcontext : "(no context)"));
1531  fsm->fcontext = _free(fsm->fcontext);
1532  }
1533  *te = '/';
1534  }
1535  if (rc)
1536  /*@innerbreak@*/ break;
1537  }
1538  if (rc) break;
1539 
1540  /* Save last validated path. */
1541 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1542  if (fsm->ldnalloc < (dnlen + 1)) {
1543  fsm->ldnalloc = dnlen + 100;
1544  fsm->ldn = (char *) xrealloc(fsm->ldn, fsm->ldnalloc);
1545  }
1546  if (fsm->ldn != NULL) { /* XXX can't happen */
1547  strcpy(fsm->ldn, fsm->path);
1548  fsm->ldnlen = dnlen;
1549  }
1550 /*@=compdef@*/
1551  }
1552  dnli = dnlFreeIterator(dnli);
1553  /*@=observertrans =dependenttrans@*/
1554 
1555  fsm->path = path;
1556  st->st_mode = st_mode; /* XXX restore st->st_mode */
1557 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1558  return rc;
1559 /*@=compdef@*/
1560 }
1561 
1562 #ifdef NOTYET
1563 
1568 static int fsmStat(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1569  /*@globals fileSystem, internalState @*/
1570  /*@modifies fsm, fileSystem, internalState @*/
1571 {
1572  int rc = 0;
1573 
1574  if (fsm->path != NULL) {
1575  int saveernno = errno;
1576  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1577  ? IOSM_LSTAT : IOSM_STAT));
1578  if (rc == IOSMERR_ENOENT) {
1579  errno = saveerrno;
1580  rc = 0;
1581  fsm->exists = 0;
1582  } else if (rc == 0) {
1583  fsm->exists = 1;
1584  }
1585  } else {
1586  /* Skip %ghost files on build. */
1587  fsm->exists = 0;
1588  }
1589  return rc;
1590 }
1591 #endif
1592 
1593 #define IS_DEV_LOG(_x) \
1594  ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
1595  !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
1596  ((_x)[sizeof("/dev/log")-1] == '\0' || \
1597  (_x)[sizeof("/dev/log")-1] == ';'))
1598 
1599 /*@-compmempass@*/
1601 {
1602 #ifdef NOTUSED
1603  iosmFileStage prevStage = fsm->stage;
1604  const char * const prev = iosmFileStageString(prevStage);
1605 #endif
1606  const char * const cur = iosmFileStageString(stage);
1607  struct stat * st = &fsm->sb;
1608  struct stat * ost = &fsm->osb;
1609  int saveerrno = errno;
1610  int rc = fsm->rc;
1611  int i;
1612 
1613 #define _fafilter(_a) \
1614  (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
1615  ? iosmFileActionString(_a) : "")
1616 
1617  if (stage & IOSM_DEAD) {
1618  /* do nothing */
1619  } else if (stage & IOSM_INTERNAL) {
1620  if (fsm->debug && !(stage & IOSM_SYSCALL))
1621  rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1622  cur,
1623  (unsigned)st->st_mode, (int)st->st_nlink,
1624  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1625  (fsm->path ? fsm->path : ""),
1626  _fafilter(fsm->action));
1627  } else {
1628  const char * apath = NULL;
1629  if (fsm->path)
1630  (void) urlPath(fsm->path, &apath);
1631  fsm->stage = stage;
1632  if (fsm->debug || !(stage & IOSM_VERBOSE))
1633  rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1634  cur,
1635  (unsigned)st->st_mode, (int)st->st_nlink,
1636  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1637  (apath ? apath + fsm->astriplen : ""),
1638  _fafilter(fsm->action));
1639  }
1640 #undef _fafilter
1641 
1642  switch (stage) {
1643  case IOSM_UNKNOWN:
1644  break;
1645  case IOSM_PKGINSTALL:
1646  while (1) {
1647  /* Clean fsm, free'ing memory. Read next archive header. */
1648  rc = fsmUNSAFE(fsm, IOSM_INIT);
1649 
1650  /* Exit on end-of-payload. */
1651  if (rc == IOSMERR_HDR_TRAILER) {
1652  rc = 0;
1653  /*@loopbreak@*/ break;
1654  }
1655 
1656  /* Exit on error. */
1657  if (rc) {
1658  fsm->postpone = 1;
1659  (void) fsmNext(fsm, IOSM_UNDO);
1660  /*@loopbreak@*/ break;
1661  }
1662 
1663  /* Extract file from archive. */
1664  rc = fsmNext(fsm, IOSM_PROCESS);
1665  if (rc) {
1666  (void) fsmNext(fsm, IOSM_UNDO);
1667  /*@loopbreak@*/ break;
1668  }
1669 
1670  /* Notify on success. */
1671  (void) fsmNext(fsm, IOSM_NOTIFY);
1672 
1673  rc = fsmNext(fsm, IOSM_FINI);
1674  if (rc) {
1675  /*@loopbreak@*/ break;
1676  }
1677  }
1678  break;
1679  case IOSM_PKGERASE:
1680  case IOSM_PKGCOMMIT:
1681  while (1) {
1682  /* Clean fsm, free'ing memory. */
1683  rc = fsmUNSAFE(fsm, IOSM_INIT);
1684 
1685  /* Exit on end-of-payload. */
1686  if (rc == IOSMERR_HDR_TRAILER) {
1687  rc = 0;
1688  /*@loopbreak@*/ break;
1689  }
1690 
1691  /* Rename/erase next item. */
1692  if (fsmNext(fsm, IOSM_FINI))
1693  /*@loopbreak@*/ break;
1694  }
1695  break;
1696  case IOSM_PKGBUILD:
1697  while (1) {
1698 
1699  rc = fsmUNSAFE(fsm, IOSM_INIT);
1700 
1701  /* Exit on end-of-payload. */
1702  if (rc == IOSMERR_HDR_TRAILER) {
1703  rc = 0;
1704  /*@loopbreak@*/ break;
1705  }
1706 
1707  /* Exit on error. */
1708  if (rc) {
1709  fsm->postpone = 1;
1710  (void) fsmNext(fsm, IOSM_UNDO);
1711  /*@loopbreak@*/ break;
1712  }
1713 
1714  /* Copy file into archive. */
1715  rc = fsmNext(fsm, IOSM_PROCESS);
1716  if (rc) {
1717  (void) fsmNext(fsm, IOSM_UNDO);
1718  /*@loopbreak@*/ break;
1719  }
1720 
1721  /* Notify on success. */
1722  (void) fsmNext(fsm, IOSM_NOTIFY);
1723 
1724  if (fsmNext(fsm, IOSM_FINI))
1725  /*@loopbreak@*/ break;
1726  }
1727 
1728  /* Flush partial sets of hard linked files. */
1729  if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) {
1730  int nlink, j;
1731  while ((fsm->li = fsm->links) != NULL) {
1732  fsm->links = fsm->li->next;
1733  fsm->li->next = NULL;
1734 
1735  /* Re-calculate link count for archive header. */
1736  for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) {
1737  if (fsm->li->filex[i] < 0)
1738  /*@innercontinue@*/ continue;
1739  nlink++;
1740  if (j == -1) j = i;
1741  }
1742  /* XXX force the contents out as well. */
1743  if (j != 0) {
1744  fsm->li->filex[0] = fsm->li->filex[j];
1745  fsm->li->filex[j] = -1;
1746  }
1747  fsm->li->sb.st_nlink = nlink;
1748 
1749  fsm->sb = fsm->li->sb; /* structure assignment */
1750  fsm->osb = fsm->sb; /* structure assignment */
1751 
1752  if (!rc) rc = writeLinkedFile(fsm);
1753 
1754  fsm->li = freeHardLink(fsm->li);
1755  }
1756  }
1757 
1758  if (!rc)
1759  rc = fsmNext(fsm, IOSM_TRAILER);
1760 
1761  break;
1762  case IOSM_CREATE:
1763  fsm->path = _free(fsm->path);
1764  fsm->lpath = _free(fsm->lpath);
1765  fsm->opath = _free(fsm->opath);
1766  fsm->dnlx = _free(fsm->dnlx);
1767 
1768  fsm->ldn = _free(fsm->ldn);
1769  fsm->ldnalloc = fsm->ldnlen = 0;
1770 
1771  fsm->rdsize = fsm->wrsize = 0;
1772  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
1773  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
1774  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
1775  fsm->rdsize = 16 * BUFSIZ;
1776  fsm->rdbuf = fsm->rdb = (char *) xmalloc(fsm->rdsize);
1777  fsm->wrsize = 16 * BUFSIZ;
1778  fsm->wrbuf = fsm->wrb = (char *) xmalloc(fsm->wrsize);
1779  }
1780 
1781  fsm->mkdirsdone = 0;
1782  fsm->ix = -1;
1783  fsm->links = NULL;
1784  fsm->li = NULL;
1785  errno = 0; /* XXX get rid of EBADF */
1786 
1787  /* Detect and create directories not explicitly in package. */
1788  if (fsm->goal == IOSM_PKGINSTALL) {
1789 /*@-compdef@*/
1790  rc = fsmNext(fsm, IOSM_MKDIRS);
1791 /*@=compdef@*/
1792  if (!rc) fsm->mkdirsdone = 1;
1793  }
1794 
1795  break;
1796  case IOSM_INIT:
1797  fsm->path = _free(fsm->path);
1798  fsm->lpath = _free(fsm->lpath);
1799  fsm->postpone = 0;
1800  fsm->diskchecked = fsm->exists = 0;
1801  fsm->subdir = NULL;
1802  fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL);
1803  fsm->action = FA_UNKNOWN;
1804  fsm->osuffix = NULL;
1805  fsm->nsuffix = NULL;
1806 
1807  if (fsm->goal == IOSM_PKGINSTALL) {
1808  /* Read next header from payload, checking for end-of-payload. */
1809  rc = fsmUNSAFE(fsm, IOSM_NEXT);
1810  }
1811  if (rc) break;
1812 
1813  /* Identify mapping index. */
1814  fsm->ix = ((fsm->goal == IOSM_PKGINSTALL)
1815  ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter));
1816 
1817 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST)) {
1818  /* Detect end-of-loop and/or mapping error. */
1819 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) {
1820  if (fsm->ix < 0) {
1821  if (fsm->goal == IOSM_PKGINSTALL) {
1822 #if 0
1824  _("archive file %s was not found in header file list\n"),
1825  fsm->path);
1826 #endif
1827  if (fsm->failedFile && *fsm->failedFile == NULL)
1828  *fsm->failedFile = xstrdup(fsm->path);
1829  rc = IOSMERR_UNMAPPED_FILE;
1830  } else {
1831  rc = IOSMERR_HDR_TRAILER;
1832  }
1833  break;
1834  }
1835 }
1836 
1837  /* On non-install, mode must be known so that dirs don't get suffix. */
1838  if (fsm->goal != IOSM_PKGINSTALL) {
1839  rpmfi fi = fsmGetFi(fsm);
1840  st->st_mode = fi->fmodes[fsm->ix];
1841  }
1842 }
1843 
1844  /* Generate file path. */
1845  rc = fsmNext(fsm, IOSM_MAP);
1846  if (rc) break;
1847 
1848  /* Perform lstat/stat for disk file. */
1849 #ifdef NOTYET
1850  rc = fsmStat(fsm);
1851 #else
1852  if (fsm->path != NULL &&
1853  !(fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))
1854  {
1855  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1856  ? IOSM_LSTAT : IOSM_STAT));
1857  if (rc == IOSMERR_ENOENT) {
1858  errno = saveerrno;
1859  rc = 0;
1860  fsm->exists = 0;
1861  } else if (rc == 0) {
1862  fsm->exists = 1;
1863  }
1864  } else {
1865  /* Skip %ghost files on build. */
1866  fsm->exists = 0;
1867  }
1868 #endif
1869  fsm->diskchecked = 1;
1870  if (rc) break;
1871 
1872  /* On non-install, the disk file stat is what's remapped. */
1873  if (fsm->goal != IOSM_PKGINSTALL)
1874  *st = *ost; /* structure assignment */
1875 
1876  /* Remap file perms, owner, and group. */
1877  rc = fsmMapAttrs(fsm);
1878  if (rc) break;
1879 
1880  fsm->postpone = iosmFileActionSkipped(fsm->action);
1881  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
1882  /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */
1883  if (S_ISREG(st->st_mode) && st->st_nlink > 1)
1884  fsm->postpone = saveHardLink(fsm);
1885  /*@=evalorder@*/
1886  }
1887 if (fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST) fsm->postpone = 1;
1888  break;
1889  case IOSM_PRE:
1890  break;
1891  case IOSM_MAP:
1892  rc = fsmMapPath(fsm);
1893  break;
1894  case IOSM_MKDIRS:
1895  rc = fsmMkdirs(fsm);
1896  break;
1897  case IOSM_RMDIRS:
1898  if (fsm->dnlx)
1899  rc = fsmRmdirs(fsm);
1900  break;
1901  case IOSM_PROCESS:
1902  if (fsm->postpone) {
1903  if (fsm->goal == IOSM_PKGINSTALL) {
1904  /* XXX Skip over file body, archive headers already done. */
1905  if (S_ISREG(st->st_mode))
1906  rc = fsmNext(fsm, IOSM_EAT);
1907  }
1908  break;
1909  }
1910 
1911  if (fsm->goal == IOSM_PKGBUILD) {
1912  if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
1913  break;
1914  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1915  struct hardLink_s * li, * prev;
1916 
1917 if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) break;
1918  rc = writeLinkedFile(fsm);
1919  if (rc) break; /* W2DO? */
1920 
1921  for (li = fsm->links, prev = NULL; li; prev = li, li = li->next)
1922  if (li == fsm->li)
1923  /*@loopbreak@*/ break;
1924 
1925  if (prev == NULL)
1926  fsm->links = fsm->li->next;
1927  else
1928  prev->next = fsm->li->next;
1929  fsm->li->next = NULL;
1930  fsm->li = freeHardLink(fsm->li);
1931  } else {
1932  rc = writeFile(fsm, 1);
1933  }
1934  break;
1935  }
1936 
1937  if (fsm->goal != IOSM_PKGINSTALL)
1938  break;
1939 
1940  if (S_ISREG(st->st_mode) && fsm->lpath != NULL) {
1941  const char * opath = fsm->opath;
1942  char * t = (char *) xmalloc(strlen(fsm->lpath+1) + strlen(fsm->suffix) + 1);
1943  (void) stpcpy(t, fsm->lpath+1);
1944  fsm->opath = t;
1945  /* XXX link(fsm->opath, fsm->path) */
1946  rc = fsmNext(fsm, IOSM_LINK);
1947  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1948  *fsm->failedFile = xstrdup(fsm->path);
1949  }
1950  fsm->opath = _free(fsm->opath);
1951  fsm->opath = opath;
1952  break; /* XXX so that delayed hard links get skipped. */
1953  }
1954  if (S_ISREG(st->st_mode)) {
1955  const char * path = fsm->path;
1956  if (fsm->osuffix)
1957  fsm->path = fsmFsPath(fsm, st, NULL, NULL);
1958  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1959 
1960  if (rc == 0 && fsm->osuffix) {
1961  const char * opath = fsm->opath;
1962  fsm->opath = fsm->path;
1963  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
1964  rc = fsmNext(fsm, IOSM_RENAME);
1965  if (!rc)
1967  _("%s saved as %s\n"),
1968  (fsm->opath ? fsm->opath : ""),
1969  (fsm->path ? fsm->path : ""));
1970  fsm->path = _free(fsm->path);
1971  fsm->opath = opath;
1972  }
1973 
1974  /*@-dependenttrans@*/
1975  fsm->path = path;
1976  /*@=dependenttrans@*/
1977  if (!(rc == IOSMERR_ENOENT)) return rc;
1978  rc = extractRegular(fsm);
1979  } else if (S_ISDIR(st->st_mode)) {
1980  mode_t st_mode = st->st_mode;
1981  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1982  if (rc == IOSMERR_ENOENT) {
1983  st->st_mode &= ~07777; /* XXX abuse st->st_mode */
1984  st->st_mode |= 00700;
1985  rc = fsmNext(fsm, IOSM_MKDIR);
1986  st->st_mode = st_mode; /* XXX restore st->st_mode */
1987  }
1988  } else if (S_ISLNK(st->st_mode)) {
1989 assert(fsm->lpath != NULL);
1990  /*@=dependenttrans@*/
1991  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1992  if (rc == IOSMERR_ENOENT)
1993  rc = fsmNext(fsm, IOSM_SYMLINK);
1994  } else if (S_ISFIFO(st->st_mode)) {
1995  mode_t st_mode = st->st_mode;
1996  /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
1997  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1998  if (rc == IOSMERR_ENOENT) {
1999  st->st_mode = 0000; /* XXX abuse st->st_mode */
2000  rc = fsmNext(fsm, IOSM_MKFIFO);
2001  st->st_mode = st_mode; /* XXX restore st->st_mode */
2002  }
2003  } else if (S_ISCHR(st->st_mode) ||
2004  S_ISBLK(st->st_mode) ||
2005  /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
2006  {
2007  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
2008  if (rc == IOSMERR_ENOENT)
2009  rc = fsmNext(fsm, IOSM_MKNOD);
2010  } else {
2011  /* XXX Repackaged payloads may be missing files. */
2012  if (fsm->repackaged)
2013  break;
2014 
2015  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2016  if (!IS_DEV_LOG(fsm->path))
2018  }
2019  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
2020  fsm->li->createdPath = fsm->li->linkIndex;
2021  rc = fsmMakeLinks(fsm);
2022  }
2023  break;
2024  case IOSM_POST:
2025  break;
2026  case IOSM_MKLINKS:
2027  rc = fsmMakeLinks(fsm);
2028  break;
2029  case IOSM_NOTIFY: /* XXX move from fsm to psm -> tsm */
2030  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
2031  rpmts ts = fsmGetTs(fsm);
2032  rpmfi fi = fsmGetFi(fsm);
2033  void * ptr;
2034  rpmuint64_t archivePos = fdGetCpioPos(fsm->cfd);
2035  if (archivePos > fi->archivePos) {
2036  fi->archivePos = (unsigned long long) archivePos;
2037  ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS,
2038  fi->archivePos, fi->archiveSize);
2039  }
2040  }
2041  break;
2042  case IOSM_UNDO:
2043  if (fsm->postpone)
2044  break;
2045  if (fsm->goal == IOSM_PKGINSTALL) {
2046  /* XXX only erase if temp fn w suffix is in use */
2047  if (fsm->sufbuf[0] != '\0')
2048  (void) fsmNext(fsm,
2049  (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK));
2050 
2051 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
2052  if (fsm->dnlx)
2053  (void) fsmNext(fsm, IOSM_RMDIRS);
2054 #endif
2055  errno = saveerrno;
2056  }
2057  if (fsm->failedFile && *fsm->failedFile == NULL)
2058  *fsm->failedFile = xstrdup(fsm->path);
2059  break;
2060  case IOSM_FINI:
2061  if (!fsm->postpone && fsm->commit) {
2062  if (fsm->goal == IOSM_PKGINSTALL)
2063  rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1)
2064  ? fsmCommitLinks(fsm) : fsmNext(fsm, IOSM_COMMIT));
2065  if (fsm->goal == IOSM_PKGCOMMIT)
2066  rc = fsmNext(fsm, IOSM_COMMIT);
2067  if (fsm->goal == IOSM_PKGERASE)
2068  rc = fsmNext(fsm, IOSM_COMMIT);
2069  }
2070  fsm->path = _free(fsm->path);
2071  fsm->lpath = _free(fsm->lpath);
2072  fsm->opath = _free(fsm->opath);
2073  memset(st, 0, sizeof(*st));
2074  memset(ost, 0, sizeof(*ost));
2075  break;
2076  case IOSM_COMMIT:
2077  /* Rename pre-existing modified or unmanaged file. */
2078  if (fsm->osuffix && fsm->diskchecked &&
2079  (fsm->exists || (fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))))
2080  {
2081  const char * opath = fsm->opath;
2082  const char * path = fsm->path;
2083  fsm->opath = fsmFsPath(fsm, st, NULL, NULL);
2084  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
2085  rc = fsmNext(fsm, IOSM_RENAME);
2086  if (!rc) {
2087  rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"),
2088  (fsm->opath ? fsm->opath : ""),
2089  (fsm->path ? fsm->path : ""));
2090  }
2091  fsm->path = _free(fsm->path);
2092  fsm->path = path;
2093  fsm->opath = _free(fsm->opath);
2094  fsm->opath = opath;
2095  }
2096 
2097  /* Remove erased files. */
2098  if (fsm->goal == IOSM_PKGERASE) {
2099  if (fsm->action == FA_ERASE) {
2100  rpmfi fi = fsmGetFi(fsm);
2101  if (S_ISDIR(st->st_mode)) {
2102  rc = fsmNext(fsm, IOSM_RMDIR);
2103  if (!rc) break;
2104  switch (rc) {
2105  case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
2106  case IOSMERR_ENOTEMPTY:
2107  /* XXX make sure that build side permits %missingok on directories. */
2108  if (fsm->fflags & RPMFILE_MISSINGOK)
2109  /*@innerbreak@*/ break;
2110 
2111  /* XXX common error message. */
2112  rpmlog(
2114  _("%s rmdir of %s failed: Directory not empty\n"),
2115  rpmfiTypeString(fi), fsm->path);
2116  /*@innerbreak@*/ break;
2117  default:
2118  rpmlog(
2119  (fsm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG),
2120  _("%s rmdir of %s failed: %s\n"),
2121  rpmfiTypeString(fi), fsm->path, strerror(errno));
2122  /*@innerbreak@*/ break;
2123  }
2124  } else {
2125  rc = fsmNext(fsm, IOSM_UNLINK);
2126  if (!rc) break;
2127  switch (rc) {
2128  case IOSMERR_ENOENT:
2129  if (fsm->fflags & RPMFILE_MISSINGOK)
2130  /*@innerbreak@*/ break;
2131  /*@fallthrough@*/
2132  default:
2133  rpmlog(
2135  _(" %s: unlink of %s failed: %s\n"),
2136  rpmfiTypeString(fi), fsm->path, strerror(errno));
2137  /*@innerbreak@*/ break;
2138  }
2139  }
2140  }
2141  /* XXX Failure to remove is not (yet) cause for failure. */
2142  if (!fsm->strict_erasures) rc = 0;
2143  break;
2144  }
2145 
2146  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2147 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) {
2148  if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) {
2149  /* Rename temporary to final file name. */
2150  if (!S_ISDIR(st->st_mode) &&
2151  (fsm->subdir || fsm->suffix || fsm->nsuffix))
2152  {
2153  fsm->opath = fsm->path;
2154  fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix);
2155  rc = fsmNext(fsm, IOSM_RENAME);
2156  if (rc)
2157  (void) Unlink(fsm->opath);
2158  else if (fsm->nsuffix) {
2159  const char * opath = fsmFsPath(fsm, st, NULL, NULL);
2160  rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
2161  (opath ? opath : ""),
2162  (fsm->path ? fsm->path : ""));
2163  opath = _free(opath);
2164  }
2165  fsm->opath = _free(fsm->opath);
2166  }
2167  /*
2168  * Set file security context (if not disabled).
2169  */
2170  if (!rc && !getuid()) {
2171  rc = fsmMapFContext(fsm);
2172  if (!rc)
2173  rc = fsmNext(fsm, IOSM_LSETFCON);
2174 /*@-dependenttrans -observertrans @*/ /* FIX: use the SELinux free wrapper */
2175  fsm->fcontext = _free(fsm->fcontext);
2176 /*@=dependenttrans =observertrans @*/
2177  }
2178  if (S_ISLNK(st->st_mode)) {
2179  if (!rc && !getuid())
2180  rc = fsmNext(fsm, IOSM_LCHOWN);
2181  } else {
2182  if (!rc && !getuid())
2183  rc = fsmNext(fsm, IOSM_CHOWN);
2184  if (!rc)
2185  rc = fsmNext(fsm, IOSM_CHMOD);
2186  if (!rc) {
2187  time_t mtime = st->st_mtime;
2188  rpmfi fi = fsmGetFi(fsm);
2189  if (fi->fmtimes)
2190  st->st_mtime = fi->fmtimes[fsm->ix];
2191  rc = fsmNext(fsm, IOSM_UTIME);
2192  st->st_mtime = mtime;
2193  }
2194  }
2195  }
2196 }
2197 
2198  /* Notify on success. */
2199  if (!rc) rc = fsmNext(fsm, IOSM_NOTIFY);
2200  else if (fsm->failedFile && *fsm->failedFile == NULL) {
2201  *fsm->failedFile = fsm->path;
2202  fsm->path = NULL;
2203  }
2204  break;
2205  case IOSM_DESTROY:
2206  fsm->path = _free(fsm->path);
2207 
2208  /* Check for hard links missing from payload. */
2209  while ((fsm->li = fsm->links) != NULL) {
2210  fsm->links = fsm->li->next;
2211  fsm->li->next = NULL;
2212  if (fsm->goal == IOSM_PKGINSTALL &&
2213  fsm->commit && fsm->li->linksLeft)
2214  {
2215  for (i = 0 ; i < fsm->li->linksLeft; i++) {
2216  if (fsm->li->filex[i] < 0)
2217  /*@innercontinue@*/ continue;
2219  if (fsm->failedFile && *fsm->failedFile == NULL) {
2220  fsm->ix = fsm->li->filex[i];
2221  if (!fsmNext(fsm, IOSM_MAP)) {
2222  *fsm->failedFile = fsm->path;
2223  fsm->path = NULL;
2224  }
2225  }
2226  /*@loopbreak@*/ break;
2227  }
2228  }
2229  if (fsm->goal == IOSM_PKGBUILD &&
2230  (fsm->mapFlags & IOSM_ALL_HARDLINKS))
2231  {
2233  }
2234  fsm->li = freeHardLink(fsm->li);
2235  }
2236  fsm->ldn = _free(fsm->ldn);
2237  fsm->ldnalloc = fsm->ldnlen = 0;
2238  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
2239  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
2240  break;
2241  case IOSM_VERIFY:
2242  if (fsm->diskchecked && !fsm->exists) {
2243  rc = IOSMERR_ENOENT;
2244  break;
2245  }
2246  if (S_ISREG(st->st_mode)) {
2247  char * path = (char *) alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
2248  (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
2249  /*
2250  * XXX HP-UX (and other os'es) don't permit unlink on busy
2251  * XXX files.
2252  */
2253  fsm->opath = fsm->path;
2254  fsm->path = path;
2255  rc = fsmNext(fsm, IOSM_RENAME);
2256  if (!rc)
2257  (void) fsmNext(fsm, IOSM_UNLINK);
2258  else
2259  rc = IOSMERR_UNLINK_FAILED;
2260  fsm->path = fsm->opath;
2261  fsm->opath = NULL;
2262  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2263  /*@notreached@*/ break;
2264  } else if (S_ISDIR(st->st_mode)) {
2265  if (S_ISDIR(ost->st_mode)) return 0;
2266  if (S_ISLNK(ost->st_mode)) {
2267  rc = fsmUNSAFE(fsm, IOSM_STAT);
2268  if (rc == IOSMERR_ENOENT) rc = 0;
2269  if (rc) break;
2270  errno = saveerrno;
2271  if (S_ISDIR(ost->st_mode)) return 0;
2272  }
2273  } else if (S_ISLNK(st->st_mode)) {
2274  if (S_ISLNK(ost->st_mode)) {
2275  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
2276  rc = fsmUNSAFE(fsm, IOSM_READLINK);
2277  errno = saveerrno;
2278  if (rc) break;
2279  if (!strcmp(fsm->lpath, fsm->rdbuf)) return 0;
2280  }
2281  } else if (S_ISFIFO(st->st_mode)) {
2282  if (S_ISFIFO(ost->st_mode)) return 0;
2283  } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
2284  if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
2285  (ost->st_rdev == st->st_rdev)) return 0;
2286  } else if (S_ISSOCK(st->st_mode)) {
2287  if (S_ISSOCK(ost->st_mode)) return 0;
2288  }
2289  /* XXX shouldn't do this with commit/undo. */
2290  rc = 0;
2291  if (fsm->stage == IOSM_PROCESS) rc = fsmNext(fsm, IOSM_UNLINK);
2292  if (rc == 0) rc = IOSMERR_ENOENT;
2293  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2294  /*@notreached@*/ break;
2295 
2296  case IOSM_UNLINK:
2297  { const char * fn = fsm->path;
2298  uint8_t * b = (uint8_t *)"";
2299  size_t blen = 0;
2300  uint8_t * d = NULL;
2301  size_t dlen = 0;
2302  uint32_t dalgo = 0;
2303  FD_t fd = NULL;
2304  struct stat sb;
2305  mode_t mode;
2306  sb.st_mode = 0;
2307  if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) {
2308  fd = Fopen(fn, "r.fdio");
2309  blen = sb.st_size;
2310  b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0);
2311  }
2312  mode = sb.st_mode;
2313  rc = rpmlioUnlink(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo);
2314  if (fd != NULL) {
2315 /*@-observertrans@*/ /* FIX: b should be initialized to NULL, not "" */
2316  (void)munmap(b, blen);
2317 /*@=observertrans@*/
2318  (void) Fclose(fd);
2319  fd = NULL;
2320  }
2321  } goto iosmcall;
2322  case IOSM_RENAME:
2323  { const char * ofn = fsm->opath;
2324  const char * fn = fsm->path;
2325  uint8_t * b = NULL;
2326  size_t blen = 0;
2327  uint8_t * d = NULL;
2328  size_t dlen = 0;
2329  uint32_t dalgo = 0;
2330  FD_t fd = NULL;
2331  struct stat sb;
2332  mode_t mode;
2333  sb.st_mode = 0;
2334  if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) {
2335  fd = Fopen(fn, "r.fdio");
2336  blen = sb.st_size;
2337  b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0);
2338  }
2339  mode = sb.st_mode;
2340  rc = rpmlioRename(rpmtsGetRdb(fsmGetTs(fsm)), ofn, fn, mode, b, blen, d, dlen, dalgo);
2341  if (fd != NULL) {
2342  (void)munmap(b, blen);
2343  (void) Fclose(fd);
2344  fd = NULL;
2345  }
2346  } goto iosmcall;
2347  case IOSM_MKDIR:
2348  rc = rpmlioMkdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2349  goto iosmcall;
2350  case IOSM_RMDIR:
2351  rc = rpmlioRmdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2352  goto iosmcall;
2353  case IOSM_LSETFCON:
2354  /* Log iff lsetfilecon() will actually be called. */
2355  if (fsm->fcontext && *fsm->fcontext
2356  && strcmp(fsm->fcontext, "<<none>>"))
2358  fsm->path, fsm->fcontext);
2359  goto iosmcall;
2360  case IOSM_CHOWN:
2361  rc = rpmlioChown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid);
2362  goto iosmcall;
2363  case IOSM_LCHOWN:
2364  rc = rpmlioLchown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid);
2365  goto iosmcall;
2366  case IOSM_CHMOD:
2367  rc = rpmlioChmod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2368  goto iosmcall;
2369  case IOSM_UTIME:
2370  rc = rpmlioUtime(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mtime, st->st_mtime);
2371  goto iosmcall;
2372  case IOSM_SYMLINK:
2373  rc = rpmlioSymlink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->lpath, fsm->path);
2374  goto iosmcall;
2375  case IOSM_LINK:
2376  rc = rpmlioLink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->opath, fsm->path);
2377  goto iosmcall;
2378  case IOSM_MKFIFO:
2379  rc = rpmlioMkfifo(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2380  goto iosmcall;
2381  case IOSM_MKNOD:
2382  rc = rpmlioMknod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode, st->st_rdev);
2383  goto iosmcall;
2384  case IOSM_LSTAT:
2385  case IOSM_STAT:
2386  case IOSM_READLINK:
2387  case IOSM_CHROOT:
2388 iosmcall:
2389  rc = iosmStage(fsm, stage);
2390  break;
2391 
2392  case IOSM_NEXT:
2393  case IOSM_EAT:
2394  case IOSM_POS:
2395  case IOSM_PAD:
2396  case IOSM_TRAILER:
2397  case IOSM_HREAD:
2398  case IOSM_HWRITE:
2399  case IOSM_DREAD:
2400  case IOSM_DWRITE:
2401  rc = iosmStage(fsm, stage);
2402  break;
2403 
2404  case IOSM_ROPEN:
2405  case IOSM_READ:
2406  case IOSM_RCLOSE:
2407  rc = iosmStage(fsm, stage);
2408  break;
2409  case IOSM_WOPEN:
2410  case IOSM_WRITE:
2411  case IOSM_WCLOSE:
2412  rc = iosmStage(fsm, stage);
2413  break;
2414 
2415  default:
2416  break;
2417  }
2418 
2419  if (!(stage & IOSM_INTERNAL)) {
2420  fsm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc);
2421  }
2422  return rc;
2423 }
2424 /*@=compmempass@*/
int arHeaderRead(void *_iosm, struct stat *st)
Read ar(1) header.
Definition: ar.c:92
const bson * b
Definition: bson.h:280
static const char * suffix[]
Definition: rpmgrep.c:188
Definition: iosm.h:34
struct hardLink_s * li
Definition: iosm.h:250
const char const double d
Definition: bson.h:800
char * ldn
Definition: iosm.h:269
int tarTrailerWrite(void *_iosm)
Write cpio trailer to payload.
Definition: tar.c:499
static void * freeHardLink(struct hardLink_s *li)
Destroy set of hard links.
Definition: fsm.c:541
static rpmts fsmGetTs(const IOSM_t fsm)
Retrieve transaction set from file state machine iterator.
Definition: fsm.c:73
struct stat sb
Definition: iosm.h:305
void * rpmtsNotify(rpmts ts, rpmte te, rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total)
Perform transaction progress notify callback.
Definition: rpmts.c:1281
const char * nsuffix
Definition: iosm.h:262
const char ** failedFile
Definition: iosm.h:254
const char bson_timestamp_t * ts
Definition: bson.h:1004
int postpone
Definition: iosm.h:272
#define IOSM_VERBOSE
Definition: iosm.h:105
static int extractRegular(IOSM_t fsm)
Create file from payload stream.
Definition: fsm.c:975
int rpmlioRename(rpmdb rpmdb, const char *oldname, const char *newname, mode_t mode, const uint8_t *b, size_t blen, const uint8_t *d, size_t dlen, uint32_t dalgo)
Definition: rpmlio.c:84
Structures used for an "rpmte" transaction element.
int commit
Definition: iosm.h:278
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
const char * osuffix
Definition: iosm.h:260
char * active
Definition: fsm.c:271
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2840
int _fsm_threads
Definition: fsm.c:65
const char * lpath
Definition: iosm.h:222
Definition: iosm.h:159
Structure(s) used for file info tag sets.
Definition: iosm.h:131
iosmFileAction action
Definition: iosm.h:301
char * wrb
Definition: iosm.h:240
const char * path
Definition: iosm.h:220
rpmfi rpmfiUnlink(rpmfi fi, const char *msg)
Unreference a file info set instance.
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
void * rpmsqThread(void *(*start)(void *arg), void *arg)
Call a function in a thread.
Definition: rpmsq.c:656
const char * dirName
Definition: iosm.h:290
rpmuint32_t digestlen
Definition: iosm.h:288
FD_t fdLink(void *cookie, const char *msg)
#define reverse(bot, top)
Definition: merge.c:102
static const char * fsmFsPath(const IOSM_t fsm, const struct stat *st, const char *subdir, const char *suffix)
Build path to file from file info, ornamented with subdir and suffix.
Definition: fsm.c:109
#define S_ISLNK(mode)
Definition: system.h:651
size_t wrsize
Definition: iosm.h:241
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2923
int repackaged
Definition: iosm.h:279
size_t lmtaboff
Definition: iosm.h:319
int errno
static int mapFind(FSMI_t iter, const char *fsmPath)
Locate archive path in file info.
Definition: fsm.c:239
unsigned int * archiveSize
Definition: iosm.h:252
void * ts
Definition: iosm.h:208
Structures used for ar(1) archives.
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
Retrieve operation timestamp from a transaction set.
Definition: pkgio.c:133
int adding
Definition: iosm.h:282
IOSMI_t iter
Definition: iosm.h:245
static int fsmMkdirs(IOSM_t fsm)
Create (if necessary) directories not explicitly included in package.
Definition: fsm.c:1441
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
int rpmlioMkfifo(rpmdb rpmdb, const char *fn, mode_t mode)
Definition: rpmlio.c:328
rpmElementType rpmteType(rpmte te)
Retrieve type of transaction element.
Definition: rpmte.c:311
rpmts rpmtsLink(rpmts ts, const char *msg)
Reference a transaction set instance.
int ix
Definition: iosm.h:246
#define S_ISSOCK(mode)
Definition: system.h:655
enum iosmFileStage_e iosmFileStage
const char * rpmfiBN(rpmfi fi)
Return current base name from file info set.
Definition: rpmfi.c:141
const unsigned char * digest
Definition: iosm.h:296
struct rpmop_s op_digest
Definition: iosm.h:321
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
int rpmlioLink(rpmdb rpmdb, const char *ln, const char *fn)
Definition: rpmlio.c:285
int cpioHeaderWrite(void *_iosm, struct stat *st)
Write cpio header.
Definition: cpio.c:225
int rpmlioRmdir(rpmdb rpmdb, const char *dn, mode_t mode)
Definition: rpmlio.c:136
Structures used for cpio(1) archives.
Definition: iosm.h:30
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
const char * subdir
Definition: iosm.h:256
Definition: iosm.h:118
int(* headerWrite)(void *_iosm, struct stat *st)
Definition: iosm.h:311
#define SUFFIX_RPMSAVE
Definition: fsm.c:97
size_t wrnb
Definition: iosm.h:243
int fsync
Definition: mongo.h:439
char * alloca()
int rpmlioMknod(rpmdb rpmdb, const char *fn, mode_t mode, dev_t dev)
Definition: rpmlio.c:308
const char * rpmfiTypeString(rpmfi fi)
Return formatted string representation of package disposition.
Definition: rpmfi.c:767
FD_t cfd
Definition: iosm.h:226
int i
Definition: fsm.c:274
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
FD_t wfd
Definition: iosm.h:236
char * lmtab
Definition: iosm.h:317
size_t rdnb
Definition: iosm.h:235
Directory name iterator.
Definition: fsm.c:268
size_t ldnlen
Definition: iosm.h:270
int multithreaded
Definition: iosm.h:281
int rpmlioCreat(rpmdb rpmdb, const char *fn, mode_t mode, const uint8_t *b, size_t blen, const uint8_t *d, size_t dlen, uint32_t dalgo)
Definition: rpmlio.c:28
const char * mode
Definition: mongo.h:440
char sufbuf[64]
Definition: iosm.h:265
int gnameToGid(const char *thisGname, gid_t *gid)
Definition: ugid.c:71
FD_t fdFree(FD_t fd, const char *msg)
const char * fdigest
Definition: iosm.h:294
int fsmStage(IOSM_t fsm, iosmFileStage stage)
File state machine driver.
Definition: fsm.c:1600
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
void * fi
Definition: iosm.h:209
struct iosm_s * IOSM_t
File state machine data.
Definition: iosm.h:17
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
Definition: rpmrpc.c:1401
int rpmsqJoin(void *thread)
Wait for thread to terminate.
Definition: rpmsq.c:671
iosmFileStage stage
Definition: iosm.h:303
#define _FSM_DEBUG
Definition: fsm.c:59
unsigned long long rpmuint64_t
Definition: rpmiotypes.h:29
iosmMapFlags mapFlags
Definition: iosm.h:286
int iosmFileActionSkipped(iosmFileAction action)
Is the file going to be skipped?
Definition: iosm.c:2678
Structures used for tar(1) archives.
#define SUFFIX_RPMORIG
Definition: fsm.c:96
int rpmlioChown(rpmdb rpmdb, const char *fn, uid_t uid, gid_t gid)
Definition: rpmlio.c:182
Definition: iosm.h:160
int rpmlioUnlink(rpmdb rpmdb, const char *fn, mode_t mode, const uint8_t *b, size_t blen, const uint8_t *d, size_t dlen, uint32_t dalgo)
Definition: rpmlio.c:56
const char * fcontext
Definition: iosm.h:298
int rpmlioLsetfilecon(rpmdb rpmdb, const char *fn, const char *context)
Definition: rpmlio.c:156
int(* trailerWrite)(void *_iosm)
Definition: iosm.h:313
#define IOSM_SYSCALL
Definition: iosm.h:107
#define IOSM_DEAD
Definition: iosm.h:108
static int dnlIndex(const DNLI_t dnli)
Definition: fsm.c:302
static int saveHardLink(IOSM_t fsm)
Save hard link in chain.
Definition: fsm.c:455
static void * dnlInitIterator(const IOSM_t fsm, int reverse)
Create directory name iterator.
Definition: fsm.c:316
int fsmMapAttrs(IOSM_t fsm)
Map file stat(2) info.
Definition: fsm.c:894
The FD_t File Handle data structure.
static rpmfi fsmGetFi(const IOSM_t fsm)
Retrieve transaction element file info from file state machine iterator.
Definition: fsm.c:87
static void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo, void *datap, size_t *lenp, int asAscii)
int rc
Definition: iosm.h:277
int fsmNext(IOSM_t fsm, iosmFileStage nstage)
File state machine driver.
Definition: fsm.c:438
Definition: iosm.h:32
size_t rdlen
Definition: iosm.h:234
static int fsmMakeLinks(IOSM_t fsm)
Create pending hard links to existing file.
Definition: fsm.c:1280
static unsigned long long fdGetCpioPos(FD_t fd)
#define _tsmask
char * rdb
Definition: iosm.h:232
static void * mapInitIterator(rpmfi fi, int reverse)
Create file info iterator.
Definition: fsm.c:163
int iosmStage(IOSM_t iosm, iosmFileStage stage)
File state machine driver.
Definition: iosm.c:1638
int reverse
Definition: iosm.h:210
Iterator across package file info, forward on install, backward on erase.
Definition: iosm.h:207
static rpmdc dc
Definition: rpmdigest.c:91
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
int nofcontexts
Definition: iosm.h:285
int fsmTeardown(void *_fsm)
Clean file state machine.
Definition: fsm.c:751
static int writeLinkedFile(IOSM_t fsm)
Write set of linked files to payload stream.
Definition: fsm.c:1206
rpmfi fi
Definition: fsm.c:269
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
int isave
Definition: fsm.c:273
iosmFileStage nstage
Definition: iosm.h:304
char * wrbuf
Definition: iosm.h:238
int rpmlioLchown(rpmdb rpmdb, const char *fn, uid_t uid, gid_t gid)
Definition: rpmlio.c:202
int cpioHeaderRead(void *_iosm, struct stat *st)
Read cpio header.
Definition: cpio.c:96
rpmdb rpmtsGetRdb(rpmts ts)
Get transaction set database handle.
Definition: pkgio.c:151
static void fdSetCpioPos(FD_t fd, long int cpioPos)
size_t wrlen
Definition: iosm.h:242
rpmuint32_t fdigestalgo
Definition: iosm.h:287
int cpioTrailerWrite(void *_iosm)
Write cpio trailer.
Definition: cpio.c:280
rpmuint32_t fflags
Definition: iosm.h:300
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
Definition: rpmfi.c:548
Definition: rpmte.h:37
const char const int i
Definition: bson.h:778
static void * dnlFreeIterator(const void *_dnli)
Destroy directory name iterator.
Definition: fsm.c:282
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
rpmfi rpmfiLink(rpmfi fi, const char *msg)
Reference a file info set instance.
int rpmlioUtime(rpmdb rpmdb, const char *fn, time_t actime, time_t modtime)
Definition: rpmlio.c:242
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
Definition: iosm.h:29
int isave
Definition: iosm.h:211
Definition: iosm.h:161
int arHeaderWrite(void *_iosm, struct stat *st)
Write ar(1) header.
Definition: ar.c:235
static int fsmCommitLinks(IOSM_t fsm)
Commit hard linked file set atomically.
Definition: fsm.c:1341
char * stpcpy(char *dest, const char *src)
#define IOSM_INTERNAL
Definition: iosm.h:106
int rpmlioChmod(rpmdb rpmdb, const char *fn, mode_t mode)
Definition: rpmlio.c:222
size_t lmtablen
Definition: iosm.h:318
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
IOSM_t newFSM(void)
Create file state machine instance.
Definition: fsm.c:551
struct dnli_s * DNLI_t
Directory name iterator.
int reverse
Definition: fsm.c:272
FD_t rfd
Definition: iosm.h:228
int nofdigests
Definition: iosm.h:284
static int writeFile(IOSM_t fsm, int writeData)
Write next item to payload stream.
Definition: fsm.c:1069
const char * iosmFileStageString(iosmFileStage a)
Return formatted string representation of file stages.
Definition: iosm.c:2703
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
struct hardLink_s * links
Definition: iosm.h:248
size_t astriplen
Definition: iosm.h:276
Structures and prototypes used for an "rpmts" transaction set.
Definition: iosm.h:36
rpmfi fi
Definition: filetriggers.h:15
#define TAR_BLOCK_SIZE
Definition: tar.h:17
static const char * dnlNextIterator(DNLI_t dnli)
Return next directory name (from file info).
Definition: fsm.c:403
int arTrailerWrite(void *_iosm)
Write ar(1) trailer.
Definition: ar.c:309
int strict_erasures
Definition: iosm.h:280
iosmFileStage goal
Definition: iosm.h:302
int _fsm_debug
Definition: fsm.c:61
#define _fi(_a)
Definition: psm.h:30
File state machine to handle a payload within an rpm package.
#define fsmUNSAFE
Definition: fsm.c:29
int fsmMapPath(IOSM_t fsm)
Map next file path and action.
Definition: fsm.c:802
#define IS_DEV_LOG(_x)
Definition: fsm.c:1593
size_t rdsize
Definition: iosm.h:233
char * rdbuf
Definition: iosm.h:230
const char * suffix
Definition: iosm.h:264
struct stat osb
Definition: iosm.h:306
int fsmSetup(void *_fsm, iosmFileStage goal, const char *afmt, const void *_ts, const void *_fi, FD_t cfd, unsigned int *archiveSize, const char **failedFile)
Load external data into file state machine.
Definition: fsm.c:627
unsigned blksize
Definition: iosm.h:308
static int cpioStrCmp(const void *a, const void *b)
Definition: fsm.c:205
IOSM_t freeFSM(IOSM_t fsm)
Destroy file state machine instance.
Definition: fsm.c:557
static int arSetup(IOSM_t iosm, rpmfi fi)
Definition: iosm.c:596
int rpmlioSymlink(rpmdb rpmdb, const char *ln, const char *fn)
Definition: rpmlio.c:262
int mkdirsdone
Definition: iosm.h:275
#define SUFFIX_RPMNEW
Definition: fsm.c:98
int debug
Definition: iosm.h:283
static int mapNextIterator(void *_iter)
Return next index into file info.
Definition: fsm.c:183
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2998
#define _(Text)
Definition: system.h:29
int diskchecked
Definition: iosm.h:273
#define xmalloc
Definition: system.h:32
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1024
struct iosmIterator_s * FSMI_t
Iterator across package file info, forward on install, backward on erase.
Definition: fsm.h:24
Access RPM indices using Berkeley DB interface(s).
const char * baseName
Definition: iosm.h:292
int unameToUid(const char *thisUname, uid_t *uid)
Definition: ugid.c:16
#define D_(Text)
Definition: system.h:526
int exists
Definition: iosm.h:274
int(* headerRead)(void *_iosm, struct stat *st)
Definition: iosm.h:309
const char * rpmsxMatch(rpmsx sx, const char *fn, mode_t mode)
Return security context for a file.
Definition: rpmsx.c:151
unsigned short * dnlx
Definition: iosm.h:267
rpmtransFlags rpmtsFlags(rpmts ts)
Get transaction flags, i.e.
Definition: rpmts.c:1334
int tarHeaderRead(void *_iosm, struct stat *st)
Read tar header from payload.
Definition: tar.c:122
static void * mapFreeIterator(void *_iter)
Destroy file info iterator.
Definition: fsm.c:141
int tarHeaderWrite(void *_iosm, struct stat *st)
Write tar header to payload.
Definition: tar.c:387
static int dnlCount(const DNLI_t dnli)
Definition: fsm.c:294
static int fsmRmdirs(IOSM_t fsm)
Remove (if created) directories not explicitly included in package.
Definition: fsm.c:1386
static int fsmMapFContext(IOSM_t fsm)
Definition: fsm.c:783
#define xrealloc
Definition: system.h:35
#define _fafilter(_a)
File name and stat information.
Definition: iosm.h:218
int rpmlioMkdir(rpmdb rpmdb, const char *dn, mode_t mode)
Definition: rpmlio.c:116
size_t ldnalloc
Definition: iosm.h:271
int j
Definition: mongo.h:438
Definition: iosm.h:33
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397
const char * opath
Definition: iosm.h:224