rpm  5.4.10
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  if (fsm->li->linksLeft > st->st_nlink) {
499  rpmlog(RPMLOG_ERR, _("Corrupted hardlinks found (count %d does not match %d), exiting.\n"), fsm->li->linksLeft, st->st_nlink);
500  return -1;
501  }
502 
503  fsm->li->filex[fsm->li->linksLeft] = fsm->ix;
504  /*@-observertrans -dependenttrans@*/
505  fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix;
506  /*@=observertrans =dependenttrans@*/
507  if (fsm->goal == IOSM_PKGINSTALL) fsm->li->linksLeft++;
508 
509  if (fsm->goal == IOSM_PKGBUILD)
510  return (fsm->li->linksLeft > 0);
511 
512  if (fsm->goal != IOSM_PKGINSTALL)
513  return 0;
514 
515  if (!(st->st_size || fsm->li->linksLeft == (int) st->st_nlink))
516  return 1;
517 
518  /* Here come the bits, time to choose a non-skipped file name. */
519  { rpmfi fi = fsmGetFi(fsm);
520 
521  for (j = fsm->li->linksLeft - 1; j >= 0; j--) {
522  ix = fsm->li->filex[j];
523  if (ix < 0 || iosmFileActionSkipped(fi->actions[ix]))
524  continue;
525  break;
526  }
527  }
528 
529  /* Are all links skipped or not encountered yet? */
530  if (ix < 0 || j < 0)
531  return 1; /* XXX W2DO? */
532 
533  /* Save the non-skipped file name and map index. */
534  fsm->li->linkIndex = j;
535  fsm->path = _free(fsm->path);
536  fsm->ix = ix;
537  rc = fsmNext(fsm, IOSM_MAP);
538  return rc;
539 }
540 
546 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li)
547  /*@modifies li @*/
548 {
549  if (li) {
550  li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */
551  li->filex = _free(li->filex);
552  }
553  return _free(li);
554 }
555 
557 {
558  IOSM_t fsm = (IOSM_t) xcalloc(1, sizeof(*fsm));
559  return fsm;
560 }
561 
563 {
564  if (fsm) {
565  fsm->path = _free(fsm->path);
566  while ((fsm->li = fsm->links) != NULL) {
567  fsm->links = fsm->li->next;
568  fsm->li->next = NULL;
569  fsm->li = freeHardLink((struct hardLink_s *)fsm->li);
570  }
571  fsm->dnlx = _free(fsm->dnlx);
572  fsm->ldn = _free(fsm->ldn);
573  fsm->iter = mapFreeIterator(fsm->iter);
574  }
575  return _free(fsm);
576 }
577 
578 #if defined(SUPPORT_AR_PAYLOADS)
579 static int arSetup(IOSM_t fsm, rpmfi fi)
580  /*@modifies fsm @*/
581 {
582  const char * path;
583  char * t;
584  size_t lmtablen = 0;
585  size_t nb;
586 
587  /* Calculate size of ar(1) long member table. */
588  if ((fi = rpmfiInit(fi, 0)) != NULL)
589  while (rpmfiNext(fi) >= 0) {
590 #ifdef NOTYET
591  if (fi->apath) {
592  const char * apath = NULL;
593  (void) urlPath(fi->apath[ix], &apath);
594  path = apath + fi->striplen;
595  } else
596 #endif
597  path = rpmfiBN(fi);
598  if ((nb = strlen(path)) < 15)
599  continue;
600  lmtablen += nb + 1; /* trailing \n */
601  }
602 
603  /* Anything to do? */
604  if (lmtablen == 0)
605  return 0;
606 
607  /* Create and load ar(1) long member table. */
608  fsm->lmtab = t = (char *) xmalloc(lmtablen + 1); /* trailing \0 */
609  fsm->lmtablen = lmtablen;
610  fsm->lmtaboff = 0;
611  if ((fi = rpmfiInit(fi, 0)) != NULL)
612  while (rpmfiNext(fi) >= 0) {
613 #ifdef NOTYET
614  if (fi->apath) {
615  const char * apath = NULL;
616  (void) urlPath(fi->apath[ix], &apath);
617  path = apath + fi->striplen;
618  } else
619 #endif
620  path = rpmfiBN(fi);
621  if ((nb = strlen(path)) < 15)
622  continue;
623  t = stpcpy(t, path);
624  *t++ = '\n';
625  }
626  *t = '\0';
627 
628  return 0;
629 }
630 #endif
631 
632 int fsmSetup(void * _fsm, iosmFileStage goal, const char * afmt,
633  const void * _ts, const void * _fi, FD_t cfd,
634  unsigned int * archiveSize, const char ** failedFile)
635 {
636  IOSM_t fsm = (IOSM_t) _fsm;
637 /*@-castexpose@*/
638  const rpmts ts = (const rpmts) _ts;
639  const rpmfi fi = (const rpmfi) _fi;
640 /*@=castexpose@*/
641 #if defined(_USE_RPMTE)
642  int reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT);
643  int adding = (rpmteType(fi->te) == TR_ADDED);
644 #else
645  int reverse = 0; /* XXX HACK: devise alternative means */
646  int adding = 1; /* XXX HACK: devise alternative means */
647 #endif
648  size_t pos = 0;
649  int rc, ec = 0;
650 
651  fsm->debug = _fsm_debug;
653  fsm->adding = adding;
654 
655 /*@+voidabstract -nullpass@*/
656 if (fsm->debug < 0)
657 fprintf(stderr, "--> fsmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", fsm, goal, afmt, (void *)ts, fi, cfd, archiveSize, failedFile);
658 /*@=voidabstract =nullpass@*/
659 
660  _iosmNext = &fsmNext;
661  if (fsm->headerRead == NULL) {
662  if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) {
663 if (fsm->debug < 0)
664 fprintf(stderr, "\ttar vectors set\n");
665  fsm->headerRead = &tarHeaderRead;
666  fsm->headerWrite = &tarHeaderWrite;
668  fsm->blksize = TAR_BLOCK_SIZE;
669  } else
670 #if defined(SUPPORT_AR_PAYLOADS)
671  if (afmt != NULL && !strcmp(afmt, "ar")) {
672 if (fsm->debug < 0)
673 fprintf(stderr, "\tar vectors set\n");
674  fsm->headerRead = &arHeaderRead;
675  fsm->headerWrite = &arHeaderWrite;
677  fsm->blksize = 2;
678  if (goal == IOSM_PKGBUILD || goal == IOSM_PKGERASE)
679  (void) arSetup(fsm, fi);
680  } else
681 #endif
682  {
683 if (fsm->debug < 0)
684 fprintf(stderr, "\tcpio vectors set\n");
685  fsm->headerRead = &cpioHeaderRead;
688  fsm->blksize = 4;
689  }
690  }
691 
692  fsm->goal = goal;
693  if (cfd != NULL) {
694 /*@-assignexpose -castexpose @*/
695  fsm->cfd = fdLink(cfd, "persist (fsm)");
696 /*@=assignexpose =castexpose @*/
697  pos = fdGetCpioPos(fsm->cfd);
698  fdSetCpioPos(fsm->cfd, 0);
699  }
700 /*@-mods@*/ /* LCL: avoid void * _ts/_fi annotations for now. */
701  fsm->iter = mapInitIterator(fi, reverse);
702 /*@-assignexpose -castexpose @*/
703  fsm->iter->ts = rpmtsLink(ts, "mapIterator");
704 /*@=assignexpose =castexpose @*/
706 /*@=mods@*/
707  fsm->nofdigests =
708  (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS))
709  ? 0 : 1;
710 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
711  fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) &&
712  fsm->goal != IOSM_PKGCOMMIT) ? 0 : 1);
713 #undef _tsmask
714 
715  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
716  void * ptr;
717  fi->archivePos = 0;
718  ptr = rpmtsNotify(ts, fi->te,
719  RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize);
720  }
721 
722  /*@-assignexpose@*/
723  fsm->archiveSize = archiveSize;
724  if (fsm->archiveSize)
725  *fsm->archiveSize = 0;
726  fsm->failedFile = failedFile;
727  if (fsm->failedFile)
728  *fsm->failedFile = NULL;
729  /*@=assignexpose@*/
730 
731  memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf));
732  if (fsm->goal == IOSM_PKGINSTALL) {
733  if (ts && rpmtsGetTid(ts) != (rpmuint32_t)-1)
734  sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts));
735  }
736 
737  ec = fsm->rc = 0;
738 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */
739  rc = fsmUNSAFE(fsm, IOSM_CREATE);
740 /*@=mods@*/
741  if (rc && !ec) ec = rc;
742 
743 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */
744  rc = fsmUNSAFE(fsm, fsm->goal);
745 /*@=mods@*/
746  if (rc && !ec) ec = rc;
747 
748  if (fsm->archiveSize && ec == 0)
749  *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos);
750 
751 /*@-nullstate@*/ /* FIX: *fsm->failedFile may be NULL */
752  return ec;
753 /*@=nullstate@*/
754 }
755 
756 int fsmTeardown(void * _fsm)
757 {
758  IOSM_t fsm = (IOSM_t) _fsm;
759  int rc = fsm->rc;
760 
761 if (fsm->debug < 0)
762 fprintf(stderr, "--> fsmTeardown(%p)\n", fsm);
763  if (!rc)
764  rc = fsmUNSAFE(fsm, IOSM_DESTROY);
765 
767  &fsm->op_digest);
768 
769  fsm->lmtab = _free(fsm->lmtab);
770  (void)rpmtsFree(fsm->iter->ts);
771  fsm->iter->ts = NULL;
772  fsm->iter = mapFreeIterator(fsm->iter);
773  if (fsm->cfd != NULL) {
774 /*@-refcounttrans@*/ /* FIX: XfdFree annotation */
775  fsm->cfd = fdFree(fsm->cfd, "persist (fsm)");
776 /*@=refcounttrans@*/
777  fsm->cfd = NULL;
778  }
779  fsm->failedFile = NULL;
780  return rc;
781 }
782 
783 /*
784  * Set file security context (if not disabled).
785  * @param fsm file state machine data
786  * @return 0 always
787  */
788 static int fsmMapFContext(IOSM_t fsm)
789  /*@modifies fsm @*/
790 {
791  fsm->fcontext = NULL;
792  if (!fsm->nofcontexts) {
793  fsm->fcontext = rpmsxMatch(NULL, fsm->path, fsm->sb.st_mode);
794 #ifdef DYING /* XXX SELinux file contexts not set from package content. */
795  { rpmfi fi = fsmGetFi(fsm);
796  int i = fsm->ix;
797 
798  /* Get file security context from package. */
799  if (fi && i >= 0 && i < (int)fi->fc)
800  fsm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL);
801  }
802 #endif
803  }
804  return 0;
805 }
806 
808 {
809  rpmfi fi = fsmGetFi(fsm); /* XXX const except for fstates */
810  int teAdding = fsm->adding;
811  int rc = 0;
812  int i = fsm->ix;
813 
814  fsm->osuffix = NULL;
815  fsm->nsuffix = NULL;
816  fsm->astriplen = 0;
817  fsm->action = FA_UNKNOWN;
818  fsm->mapFlags = fi->mapflags;
819 
820  if (fi && i >= 0 && i < (int)fi->fc) {
821 
822  fsm->astriplen = fi->astriplen;
823  fsm->action = (fi->actions ? fi->actions[i] : fi->action);
824  fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags);
825  fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
826 
827  /* src rpms have simple base name in payload. */
828  fsm->dirName = fi->dnl[fi->dil[i]];
829  fsm->baseName = fi->bnl[i];
830 
831  switch (fsm->action) {
832  case FA_SKIP:
833  break;
834  case FA_UNKNOWN:
835  break;
836 
837  case FA_COPYOUT:
838  break;
839  case FA_COPYIN:
840  case FA_CREATE:
841 assert(teAdding);
842  break;
843 
844  case FA_SKIPNSTATE:
845  if (fi->fstates && teAdding)
846  fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED;
847  break;
848 
849  case FA_SKIPNETSHARED:
850  if (fi->fstates && teAdding)
851  fi->fstates[i] = RPMFILE_STATE_NETSHARED;
852  break;
853 
854  case FA_SKIPCOLOR:
855  if (fi->fstates && teAdding)
856  fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR;
857  break;
858 
859  case FA_BACKUP:
860  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
861  fsm->osuffix = (teAdding ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE);
862  break;
863 
864  case FA_ALTNAME:
865 assert(teAdding);
866  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
867  fsm->nsuffix = SUFFIX_RPMNEW;
868  break;
869 
870  case FA_SAVE:
871 assert(teAdding);
872  if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
873  fsm->osuffix = SUFFIX_RPMSAVE;
874  break;
875  case FA_ERASE:
876 #if 0 /* XXX is this a genhdlist fix? */
877  assert(rpmteType(fi->te) == TR_REMOVED);
878 #endif
879  /*
880  * XXX TODO: %ghost probably shouldn't be removed, but that changes
881  * legacy rpm behavior.
882  */
883  break;
884  default:
885  break;
886  }
887 
888  if ((fsm->mapFlags & IOSM_MAP_PATH) || fsm->nsuffix) {
889  const struct stat * st = &fsm->sb;
890  fsm->path = _free(fsm->path);
891  fsm->path = fsmFsPath(fsm, st, fsm->subdir,
892  (fsm->suffix ? fsm->suffix : fsm->nsuffix));
893  }
894  }
895  return rc;
896 }
897 
899 {
900  struct stat * st = &fsm->sb;
901  rpmfi fi = fsmGetFi(fsm);
902  int i = fsm->ix;
903 
904  if (fi && i >= 0 && i < (int) fi->fc) {
905  mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
906  ino_t finalInode = (fi->finodes ? (ino_t)fi->finodes[i] : 0);
907  mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms);
908  dev_t finalRdev = (dev_t)(fi->frdevs ? fi->frdevs[i] : 0);
909  rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
910  uid_t uid = fi->uid;
911  gid_t gid = fi->gid;
912 
913  /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during
914  installation of _source_ RPMs. Instead, let it use the current
915  run-time owner/group, because most of the time the owner/group in
916  the source RPM (which is the owner/group of the files as staying on
917  the package author system) is not existing on the target system, of
918  course. */
919  if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
920  if (!fi->isSource) {
921  if (fsm->goal == IOSM_PKGINSTALL)
923  _("user %s does not exist - using root\n"), fi->fuser[i]);
924  uid = 0;
925  finalMode &= ~S_ISUID; /* turn off suid bit */
926  }
927  }
928 
929  if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
930  if (!fi->isSource) {
931  if (fsm->goal == IOSM_PKGINSTALL)
933  _("group %s does not exist - using root\n"), fi->fgroup[i]);
934  gid = 0;
935  finalMode &= ~S_ISGID; /* turn off sgid bit */
936  }
937  }
938 
939  if (fsm->mapFlags & IOSM_MAP_MODE)
940  st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
941  if (fsm->mapFlags & IOSM_MAP_TYPE) {
942  st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
943  if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
944  && st->st_nlink == 0)
945  st->st_nlink = 1;
946  st->st_ino = finalInode;
947  st->st_rdev = finalRdev;
948  st->st_mtime = finalMtime;
949  }
950  if (fsm->mapFlags & IOSM_MAP_UID)
951  st->st_uid = uid;
952  if (fsm->mapFlags & IOSM_MAP_GID)
953  st->st_gid = gid;
954 
955  /*
956  * Set file digest (if not disabled).
957  */
958  if (!fsm->nofdigests) {
959  fsm->fdigestalgo = fi->digestalgo;
960  fsm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL);
961  fsm->digestlen = fi->digestlen;
962  fsm->digest = (fi->digests ? (fi->digests + (fsm->digestlen * i)) : NULL);
963  } else {
964  fsm->fdigestalgo = 0;
965  fsm->fdigest = NULL;
966  fsm->digestlen = 0;
967  fsm->digest = NULL;
968  }
969  }
970  return 0;
971 }
972 
978 /*@-compdef@*/
979 static int extractRegular(/*@special@*/ IOSM_t fsm)
980  /*@uses fsm->fdigest, fsm->digest, fsm->sb, fsm->wfd @*/
981  /*@globals h_errno, fileSystem, internalState @*/
982  /*@modifies fsm, fileSystem, internalState @*/
983 {
984  const struct stat * st = &fsm->sb;
985  size_t left = (size_t) st->st_size;
986  int rc = 0;
987  int xx;
988 
989  { const char * fn = fsm->path;
990  mode_t mode = st->st_mode;
991  uint8_t * b = (uint8_t *)"";
992  size_t blen = 1;
993  const uint8_t * d = fsm->digest;
994  size_t dlen = fsm->digestlen;
995  uint32_t dalgo = fsm->fdigestalgo;
996 
997  xx = rpmlioCreat(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo);
998  }
999 
1000  rc = fsmNext(fsm, IOSM_WOPEN);
1001  if (rc)
1002  goto exit;
1003 
1004  if (st->st_size > 0 && (fsm->fdigest != NULL || fsm->digest != NULL))
1005  fdInitDigest(fsm->wfd, fsm->fdigestalgo, 0);
1006 
1007  while (left) {
1008 
1009  fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
1010  rc = fsmNext(fsm, IOSM_DREAD);
1011  if (rc)
1012  goto exit;
1013 
1014  rc = fsmNext(fsm, IOSM_WRITE);
1015  if (rc)
1016  goto exit;
1017 
1018  left -= fsm->wrnb;
1019 
1020  /* Notify iff progress, completion is done elsewhere */
1021  if (!rc && left)
1022  (void) fsmNext(fsm, IOSM_NOTIFY);
1023  }
1024 
1025 #ifdef DYING
1026 /* Measurements from installing kernel-source package:
1027  * +fsync
1028  * total: 1 0.000000 MB 640.854524 secs
1029  * +fdatasync
1030  * total: 1 0.000000 MB 419.983200 secs
1031  * w/o fsync/fdsatasync:
1032  * total: 1 0.000000 MB 12.492918 secs
1033  */
1034  xx = fsync(Fileno(fsm->wfd));
1035 #endif
1036 
1037  if (st->st_size > 0 && (fsm->fdigest || fsm->digest)) {
1038  void * digest = NULL;
1039  int asAscii = (fsm->digest == NULL ? 1 : 0);
1040 
1041  (void) Fflush(fsm->wfd);
1042  fdFiniDigest(fsm->wfd, fsm->fdigestalgo, &digest, NULL, asAscii);
1043 
1044  if (digest == NULL) {
1046  goto exit;
1047  }
1048 
1049  if (fsm->digest != NULL) {
1050  if (memcmp(digest, fsm->digest, fsm->digestlen))
1052  } else {
1053  if (strcmp(digest, fsm->fdigest))
1055  }
1056  digest = _free(digest);
1057  }
1058 
1059 exit:
1060  (void) fsmNext(fsm, IOSM_WCLOSE);
1061 
1062  return rc;
1063 }
1064 /*@=compdef@*/
1065 
1072 /*@-compdef -compmempass@*/
1073 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t fsm, int writeData)
1074  /*@uses fsm->path, fsm->opath, fsm->sb, fsm->osb, fsm->cfd @*/
1075  /*@globals h_errno, fileSystem, internalState @*/
1076  /*@modifies fsm, fileSystem, internalState @*/
1077 {
1078  const char * path = fsm->path;
1079  const char * opath = fsm->opath;
1080  struct stat * st = &fsm->sb;
1081  struct stat * ost = &fsm->osb;
1082  size_t left;
1083  int xx;
1084  int rc;
1085 
1086  st->st_size = (writeData ? ost->st_size : 0);
1087 
1088  if (S_ISDIR(st->st_mode)) {
1089  st->st_size = 0;
1090  } else if (S_ISLNK(st->st_mode)) {
1091  /*
1092  * While linux puts the size of a symlink in the st_size field,
1093  * I don't think that's a specified standard.
1094  */
1095  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
1096  rc = fsmUNSAFE(fsm, IOSM_READLINK);
1097  if (rc) goto exit;
1098  st->st_size = fsm->rdnb;
1099  fsm->lpath = xstrdup(fsm->rdbuf); /* XXX save readlink return. */
1100  }
1101 
1102  if (fsm->mapFlags & IOSM_MAP_ABSOLUTE) {
1103  size_t nb= strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof(".");
1104  char * t = (char *) alloca(nb);
1105  *t = '\0';
1106  fsm->path = t;
1107  if (fsm->mapFlags & IOSM_MAP_ADDDOT)
1108  *t++ = '.';
1109  t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName);
1110  } else if (fsm->mapFlags & IOSM_MAP_PATH) {
1111  rpmfi fi = fsmGetFi(fsm);
1112  if (fi->apath) {
1113  const char * apath = NULL;
1114  (void) urlPath(fi->apath[fsm->ix], &apath);
1115  fsm->path = apath + fi->striplen;
1116  } else
1117  fsm->path = fi->bnl[fsm->ix];
1118  }
1119 
1120  rc = fsmNext(fsm, IOSM_HWRITE);
1121  fsm->path = path;
1122  if (rc) goto exit;
1123 
1124  if (writeData && S_ISREG(st->st_mode)) {
1125 #if defined(HAVE_MMAP)
1126  char * rdbuf = NULL;
1127  void * mapped = (void *)-1;
1128  size_t nmapped = 0;
1129  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */
1130  int use_mmap = (st->st_size <= 0x07ffffff);
1131 #endif
1132 
1133  rc = fsmNext(fsm, IOSM_ROPEN);
1134  if (rc) goto exit;
1135 
1136  /* XXX unbuffered mmap generates *lots* of fdio debugging */
1137 #if defined(HAVE_MMAP)
1138  if (use_mmap) {
1139  mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0);
1140  if (mapped != (void *)-1) {
1141  rdbuf = fsm->rdbuf;
1142  fsm->rdbuf = (char *) mapped;
1143  fsm->rdlen = nmapped = st->st_size;
1144 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1145  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1146 #endif
1147  }
1148  }
1149 #endif
1150 
1151  left = st->st_size;
1152 
1153  while (left) {
1154 #if defined(HAVE_MMAP)
1155  if (mapped != (void *)-1) {
1156  fsm->rdnb = nmapped;
1157  } else
1158 #endif
1159  {
1160  fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
1161  rc = fsmNext(fsm, IOSM_READ);
1162  if (rc) goto exit;
1163  }
1164 
1165  /* XXX DWRITE uses rdnb for I/O length. */
1166  rc = fsmNext(fsm, IOSM_DWRITE);
1167  if (rc) goto exit;
1168 
1169  left -= fsm->wrnb;
1170  }
1171 
1172 #if defined(HAVE_MMAP)
1173  if (mapped != (void *)-1) {
1174 /* XXX splint misses size_t 2nd arg. */
1175 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC);
1176 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1177  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1178 #endif
1179  xx = munmap(mapped, nmapped);
1180  fsm->rdbuf = rdbuf;
1181  } else
1182 #endif
1183  xx = fsync(Fileno(fsm->rfd));
1184 
1185  }
1186 
1187  rc = fsmNext(fsm, IOSM_PAD);
1188  if (rc) goto exit;
1189 
1190  rc = 0;
1191 
1192 exit:
1193  if (fsm->rfd != NULL)
1194  (void) fsmNext(fsm, IOSM_RCLOSE);
1195 /*@-dependenttrans@*/
1196  fsm->opath = opath;
1197  fsm->path = path;
1198 /*@=dependenttrans@*/
1199  return rc;
1200 }
1201 /*@=compdef =compmempass@*/
1202 
1208 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1209  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->li, fsm->failedFile @*/
1210  /*@globals h_errno, fileSystem, internalState @*/
1211  /*@modifies fsm, fileSystem, internalState @*/
1212 {
1213  const char * path = fsm->path;
1214  const char * lpath = fsm->lpath;
1215  const char * nsuffix = fsm->nsuffix;
1216  int iterIndex = fsm->ix;
1217  int ec = 0;
1218  int rc;
1219  int i;
1220  const char * linkpath = NULL;
1221  int firstfile = 1;
1222 
1223  fsm->path = NULL;
1224  fsm->lpath = NULL;
1225  fsm->nsuffix = NULL;
1226  fsm->ix = -1;
1227 
1228  for (i = fsm->li->nlink - 1; i >= 0; i--) {
1229 
1230  if (fsm->li->filex[i] < 0) continue;
1231 
1232  fsm->ix = fsm->li->filex[i];
1233 /*@-compdef@*/
1234  rc = fsmNext(fsm, IOSM_MAP);
1235 /*@=compdef@*/
1236 
1237  /* XXX tar and cpio have to do things differently. */
1238  if (fsm->headerWrite == tarHeaderWrite) {
1239  if (firstfile) {
1240  const char * apath = NULL;
1241  char *t;
1242  (void) urlPath(fsm->path, &apath);
1243  /* Remove the buildroot prefix. */
1244  t = (char *) xmalloc(sizeof(".") + strlen(apath + fsm->astriplen));
1245  (void) stpcpy( stpcpy(t, "."), apath + fsm->astriplen);
1246  linkpath = t;
1247  firstfile = 0;
1248  } else
1249  fsm->lpath = linkpath;
1250 
1251  /* Write data after first link for tar. */
1252  rc = writeFile(fsm, (fsm->lpath == NULL));
1253  } else {
1254  /* Write data after last link for cpio. */
1255  rc = writeFile(fsm, (i == 0));
1256  }
1257  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1258  ec = rc;
1259  *fsm->failedFile = xstrdup(fsm->path);
1260  }
1261 
1262  fsm->path = _free(fsm->path);
1263  fsm->li->filex[i] = -1;
1264  }
1265 
1266 /*@-dependenttrans@*/
1267  linkpath = _free(linkpath);
1268 /*@=dependenttrans@*/
1269  fsm->ix = iterIndex;
1270  fsm->nsuffix = nsuffix;
1271  fsm->lpath = lpath;
1272  fsm->path = path;
1273  return ec;
1274 }
1275 
1281 /*@-compdef@*/
1282 static int fsmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1283  /*@uses fsm->path, fsm->opath, fsm->nsuffix, fsm->ix, fsm->li @*/
1284  /*@globals h_errno, fileSystem, internalState @*/
1285  /*@modifies fsm, fileSystem, internalState @*/
1286 {
1287  const char * path = fsm->path;
1288  const char * opath = fsm->opath;
1289  const char * nsuffix = fsm->nsuffix;
1290  int iterIndex = fsm->ix;
1291  int ec = 0;
1292  int rc;
1293  int i;
1294 
1295  fsm->path = NULL;
1296  fsm->opath = NULL;
1297  fsm->nsuffix = NULL;
1298  fsm->ix = -1;
1299 
1300  fsm->ix = fsm->li->filex[fsm->li->createdPath];
1301  rc = fsmNext(fsm, IOSM_MAP);
1302  fsm->opath = fsm->path;
1303  fsm->path = NULL;
1304  for (i = 0; i < fsm->li->nlink; i++) {
1305  if (fsm->li->filex[i] < 0) continue;
1306  if (fsm->li->createdPath == i) continue;
1307 
1308  fsm->ix = fsm->li->filex[i];
1309  fsm->path = _free(fsm->path);
1310  rc = fsmNext(fsm, IOSM_MAP);
1311  if (iosmFileActionSkipped(fsm->action)) continue;
1312 
1313  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1314  if (!rc) continue;
1315  if (!(rc == IOSMERR_ENOENT)) break;
1316 
1317  /* XXX link(fsm->opath, fsm->path) */
1318  rc = fsmNext(fsm, IOSM_LINK);
1319  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1320  ec = rc;
1321  *fsm->failedFile = xstrdup(fsm->path);
1322  }
1323 
1324  fsm->li->linksLeft--;
1325  }
1326  fsm->path = _free(fsm->path);
1327  fsm->opath = _free(fsm->opath);
1328 
1329  fsm->ix = iterIndex;
1330  fsm->nsuffix = nsuffix;
1331  fsm->path = path;
1332  fsm->opath = opath;
1333  return ec;
1334 }
1335 /*@=compdef@*/
1336 
1342 /*@-compdef@*/
1343 static int fsmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1344  /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->sb,
1345  fsm->li, fsm->links @*/
1346  /*@globals h_errno, fileSystem, internalState @*/
1347  /*@modifies fsm, fileSystem, internalState @*/
1348 {
1349  const char * path = fsm->path;
1350  const char * nsuffix = fsm->nsuffix;
1351  int iterIndex = fsm->ix;
1352  struct stat * st = &fsm->sb;
1353  int rc = 0;
1354  int i;
1355 
1356  fsm->path = NULL;
1357  fsm->nsuffix = NULL;
1358  fsm->ix = -1;
1359 
1360  for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
1361  if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
1362  break;
1363  }
1364 
1365  for (i = 0; i < fsm->li->nlink; i++) {
1366  if (fsm->li->filex[i] < 0) continue;
1367  fsm->ix = fsm->li->filex[i];
1368  rc = fsmNext(fsm, IOSM_MAP);
1369  if (!iosmFileActionSkipped(fsm->action))
1370  rc = fsmNext(fsm, IOSM_COMMIT);
1371  fsm->path = _free(fsm->path);
1372  fsm->li->filex[i] = -1;
1373  }
1374 
1375  fsm->ix = iterIndex;
1376  fsm->nsuffix = nsuffix;
1377  fsm->path = path;
1378  return rc;
1379 }
1380 /*@=compdef@*/
1381 
1387 static int fsmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1388  /*@uses fsm->path, fsm->dnlx, fsm->ldn, fsm->rdbuf, fsm->iter @*/
1389  /*@globals h_errno, fileSystem, internalState @*/
1390  /*@modifies fsm, fileSystem, internalState @*/
1391 {
1392  const char * path = fsm->path;
1393  void * dnli = dnlInitIterator(fsm, 1);
1394  char * dn = fsm->rdbuf;
1395  int dc = dnlCount(dnli);
1396  int rc = 0;
1397 
1398  fsm->path = NULL;
1399  dn[0] = '\0';
1400  /*@-observertrans -dependenttrans@*/
1401  if (fsm->ldn != NULL && fsm->dnlx != NULL)
1402  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1403  size_t dnlen = strlen(fsm->path);
1404  char * te;
1405 
1406  dc = dnlIndex(dnli);
1407  if (fsm->dnlx[dc] < 1 || (size_t)fsm->dnlx[dc] >= dnlen)
1408  continue;
1409 
1410  /* Copy to avoid const on fsm->path. */
1411  te = stpcpy(dn, fsm->path) - 1;
1412  fsm->path = dn;
1413 
1414  /* Remove generated directories. */
1415  /*@-usereleased@*/ /* LCL: te used after release? */
1416  do {
1417  if (*te == '/') {
1418  *te = '\0';
1419 /*@-compdef@*/
1420  rc = fsmNext(fsm, IOSM_RMDIR);
1421 /*@=compdef@*/
1422  *te = '/';
1423  }
1424  if (rc)
1425  /*@innerbreak@*/ break;
1426  te--;
1427  } while ((te - fsm->path) > fsm->dnlx[dc]);
1428  /*@=usereleased@*/
1429  }
1430  dnli = dnlFreeIterator(dnli);
1431  /*@=observertrans =dependenttrans@*/
1432 
1433  fsm->path = path;
1434  return rc;
1435 }
1436 
1442 static int fsmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1443  /*@uses fsm->path, fsm->sb, fsm->osb, fsm->rdbuf, fsm->iter,
1444  fsm->ldn, fsm->ldnlen, fsm->ldnalloc @*/
1445  /*@defines fsm->dnlx, fsm->ldn @*/
1446  /*@globals h_errno, fileSystem, internalState @*/
1447  /*@modifies fsm, fileSystem, internalState @*/
1448 {
1449  struct stat * st = &fsm->sb;
1450  struct stat * ost = &fsm->osb;
1451  const char * path = fsm->path;
1452  mode_t st_mode = st->st_mode;
1453  void * dnli = dnlInitIterator(fsm, 0);
1454  char * dn = fsm->rdbuf;
1455  int dc = dnlCount(dnli);
1456  int rc = 0;
1457  size_t i;
1458 
1459  fsm->path = NULL;
1460 
1461  dn[0] = '\0';
1462  fsm->dnlx = (unsigned short *) (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL);
1463  /*@-observertrans -dependenttrans@*/
1464  if (fsm->dnlx != NULL)
1465  while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
1466  size_t dnlen = strlen(fsm->path);
1467  char * te;
1468 
1469  dc = dnlIndex(dnli);
1470  if (dc < 0) continue;
1471  fsm->dnlx[dc] = (unsigned short) dnlen;
1472  if (dnlen <= 1)
1473  continue;
1474 
1475  /*@-compdef -nullpass@*/ /* FIX: fsm->ldn not defined ??? */
1476  if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn))
1477  continue;
1478  /*@=compdef =nullpass@*/
1479 
1480  /* Copy to avoid const on fsm->path. */
1481  (void) stpcpy(dn, fsm->path);
1482  fsm->path = dn;
1483 
1484  /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
1485  (void) urlPath(dn, (const char **)&te);
1486  for (i = 1, te++; *te != '\0'; te++, i++) {
1487  if (*te != '/')
1488  /*@innercontinue@*/ continue;
1489 
1490  *te = '\0';
1491 
1492  /* Already validated? */
1493  /*@-usedef -compdef -nullpass -nullderef@*/
1494  if (i < fsm->ldnlen &&
1495  (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') &&
1496  !strncmp(fsm->path, fsm->ldn, i))
1497  {
1498  *te = '/';
1499  /* Move pre-existing path marker forward. */
1500  fsm->dnlx[dc] = (te - dn);
1501  /*@innercontinue@*/ continue;
1502  }
1503  /*@=usedef =compdef =nullpass =nullderef@*/
1504 
1505  /* Validate next component of path. */
1506  rc = fsmUNSAFE(fsm, IOSM_LSTAT);
1507  *te = '/';
1508 
1509  /* Directory already exists? */
1510  if (rc == 0 && S_ISDIR(ost->st_mode)) {
1511  /* Move pre-existing path marker forward. */
1512  fsm->dnlx[dc] = (te - dn);
1513  } else if (rc == IOSMERR_ENOENT) {
1514  rpmfi fi = fsmGetFi(fsm);
1515  *te = '\0';
1516  st->st_mode = S_IFDIR | (fi->dperms & 07777);
1517  rc = fsmNext(fsm, IOSM_MKDIR);
1518  if (!rc) {
1519  /* XXX FIXME? only new dir will have context set. */
1520  /* Get file security context from patterns. */
1521  if (!fsm->nofcontexts) {
1522  fsm->fcontext =
1523  rpmsxMatch(NULL, fsm->path, st->st_mode);
1524  if (fsm->fcontext != NULL)
1525  rc = fsmNext(fsm, IOSM_LSETFCON);
1526  } else
1527  fsm->fcontext = NULL;
1529  D_("%s directory created with perms %04o, context %s.\n"),
1530  fsm->path, (unsigned)(st->st_mode & 07777),
1531  (fsm->fcontext ? fsm->fcontext : "(no context)"));
1532  fsm->fcontext = _free(fsm->fcontext);
1533  }
1534  *te = '/';
1535  }
1536  if (rc)
1537  /*@innerbreak@*/ break;
1538  }
1539  if (rc) break;
1540 
1541  /* Save last validated path. */
1542 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1543  if (fsm->ldnalloc < (dnlen + 1)) {
1544  fsm->ldnalloc = dnlen + 100;
1545  fsm->ldn = (char *) xrealloc(fsm->ldn, fsm->ldnalloc);
1546  }
1547  if (fsm->ldn != NULL) { /* XXX can't happen */
1548  strcpy(fsm->ldn, fsm->path);
1549  fsm->ldnlen = dnlen;
1550  }
1551 /*@=compdef@*/
1552  }
1553  dnli = dnlFreeIterator(dnli);
1554  /*@=observertrans =dependenttrans@*/
1555 
1556  fsm->path = path;
1557  st->st_mode = st_mode; /* XXX restore st->st_mode */
1558 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1559  return rc;
1560 /*@=compdef@*/
1561 }
1562 
1563 #ifdef NOTYET
1564 
1569 static int fsmStat(/*@special@*/ /*@partial@*/ IOSM_t fsm)
1570  /*@globals fileSystem, internalState @*/
1571  /*@modifies fsm, fileSystem, internalState @*/
1572 {
1573  int rc = 0;
1574 
1575  if (fsm->path != NULL) {
1576  int saveernno = errno;
1577  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1578  ? IOSM_LSTAT : IOSM_STAT));
1579  if (rc == IOSMERR_ENOENT) {
1580  errno = saveerrno;
1581  rc = 0;
1582  fsm->exists = 0;
1583  } else if (rc == 0) {
1584  fsm->exists = 1;
1585  }
1586  } else {
1587  /* Skip %ghost files on build. */
1588  fsm->exists = 0;
1589  }
1590  return rc;
1591 }
1592 #endif
1593 
1594 #define IS_DEV_LOG(_x) \
1595  ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
1596  !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
1597  ((_x)[sizeof("/dev/log")-1] == '\0' || \
1598  (_x)[sizeof("/dev/log")-1] == ';'))
1599 
1600 /*@-compmempass@*/
1602 {
1603 #ifdef NOTUSED
1604  iosmFileStage prevStage = fsm->stage;
1605  const char * const prev = iosmFileStageString(prevStage);
1606 #endif
1607  const char * const cur = iosmFileStageString(stage);
1608  struct stat * st = &fsm->sb;
1609  struct stat * ost = &fsm->osb;
1610  int saveerrno = errno;
1611  int rc = fsm->rc;
1612  int i;
1613 
1614 #define _fafilter(_a) \
1615  (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
1616  ? iosmFileActionString(_a) : "")
1617 
1618  if (stage & IOSM_DEAD) {
1619  /* do nothing */
1620  } else if (stage & IOSM_INTERNAL) {
1621  if (fsm->debug && !(stage & IOSM_SYSCALL))
1622  rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1623  cur,
1624  (unsigned)st->st_mode, (int)st->st_nlink,
1625  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1626  (fsm->path ? fsm->path : ""),
1627  _fafilter(fsm->action));
1628  } else {
1629  const char * apath = NULL;
1630  if (fsm->path)
1631  (void) urlPath(fsm->path, &apath);
1632  fsm->stage = stage;
1633  if (fsm->debug || !(stage & IOSM_VERBOSE))
1634  rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1635  cur,
1636  (unsigned)st->st_mode, (int)st->st_nlink,
1637  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1638  (apath ? apath + fsm->astriplen : ""),
1639  _fafilter(fsm->action));
1640  }
1641 #undef _fafilter
1642 
1643  switch (stage) {
1644  case IOSM_UNKNOWN:
1645  break;
1646  case IOSM_PKGINSTALL:
1647  while (1) {
1648  /* Clean fsm, free'ing memory. Read next archive header. */
1649  rc = fsmUNSAFE(fsm, IOSM_INIT);
1650 
1651  /* Exit on end-of-payload. */
1652  if (rc == IOSMERR_HDR_TRAILER) {
1653  rc = 0;
1654  /*@loopbreak@*/ break;
1655  }
1656 
1657  /* Exit on error. */
1658  if (rc) {
1659  fsm->postpone = 1;
1660  (void) fsmNext(fsm, IOSM_UNDO);
1661  /*@loopbreak@*/ break;
1662  }
1663 
1664  /* Extract file from archive. */
1665  rc = fsmNext(fsm, IOSM_PROCESS);
1666  if (rc) {
1667  (void) fsmNext(fsm, IOSM_UNDO);
1668  /*@loopbreak@*/ break;
1669  }
1670 
1671  /* Notify on success. */
1672  (void) fsmNext(fsm, IOSM_NOTIFY);
1673 
1674  rc = fsmNext(fsm, IOSM_FINI);
1675  if (rc) {
1676  /*@loopbreak@*/ break;
1677  }
1678  }
1679  break;
1680  case IOSM_PKGERASE:
1681  case IOSM_PKGCOMMIT:
1682  while (1) {
1683  /* Clean fsm, free'ing memory. */
1684  rc = fsmUNSAFE(fsm, IOSM_INIT);
1685 
1686  /* Exit on end-of-payload. */
1687  if (rc == IOSMERR_HDR_TRAILER) {
1688  rc = 0;
1689  /*@loopbreak@*/ break;
1690  }
1691 
1692  /* Rename/erase next item. */
1693  if (fsmNext(fsm, IOSM_FINI))
1694  /*@loopbreak@*/ break;
1695  }
1696  break;
1697  case IOSM_PKGBUILD:
1698  while (1) {
1699 
1700  rc = fsmUNSAFE(fsm, IOSM_INIT);
1701 
1702  /* Exit on end-of-payload. */
1703  if (rc == IOSMERR_HDR_TRAILER) {
1704  rc = 0;
1705  /*@loopbreak@*/ break;
1706  }
1707 
1708  /* Exit on error. */
1709  if (rc) {
1710  fsm->postpone = 1;
1711  (void) fsmNext(fsm, IOSM_UNDO);
1712  /*@loopbreak@*/ break;
1713  }
1714 
1715  /* Copy file into archive. */
1716  rc = fsmNext(fsm, IOSM_PROCESS);
1717  if (rc) {
1718  (void) fsmNext(fsm, IOSM_UNDO);
1719  /*@loopbreak@*/ break;
1720  }
1721 
1722  /* Notify on success. */
1723  (void) fsmNext(fsm, IOSM_NOTIFY);
1724 
1725  if (fsmNext(fsm, IOSM_FINI))
1726  /*@loopbreak@*/ break;
1727  }
1728 
1729  /* Flush partial sets of hard linked files. */
1730  if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) {
1731  int nlink, j;
1732  while ((fsm->li = fsm->links) != NULL) {
1733  fsm->links = fsm->li->next;
1734  fsm->li->next = NULL;
1735 
1736  /* Re-calculate link count for archive header. */
1737  for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) {
1738  if (fsm->li->filex[i] < 0)
1739  /*@innercontinue@*/ continue;
1740  nlink++;
1741  if (j == -1) j = i;
1742  }
1743  /* XXX force the contents out as well. */
1744  if (j != 0) {
1745  fsm->li->filex[0] = fsm->li->filex[j];
1746  fsm->li->filex[j] = -1;
1747  }
1748  fsm->li->sb.st_nlink = nlink;
1749 
1750  fsm->sb = fsm->li->sb; /* structure assignment */
1751  fsm->osb = fsm->sb; /* structure assignment */
1752 
1753  if (!rc) rc = writeLinkedFile(fsm);
1754 
1755  fsm->li = freeHardLink(fsm->li);
1756  }
1757  }
1758 
1759  if (!rc)
1760  rc = fsmNext(fsm, IOSM_TRAILER);
1761 
1762  break;
1763  case IOSM_CREATE:
1764  fsm->path = _free(fsm->path);
1765  fsm->lpath = _free(fsm->lpath);
1766  fsm->opath = _free(fsm->opath);
1767  fsm->dnlx = _free(fsm->dnlx);
1768 
1769  fsm->ldn = _free(fsm->ldn);
1770  fsm->ldnalloc = fsm->ldnlen = 0;
1771 
1772  fsm->rdsize = fsm->wrsize = 0;
1773  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
1774  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
1775  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
1776  fsm->rdsize = 16 * BUFSIZ;
1777  fsm->rdbuf = fsm->rdb = (char *) xmalloc(fsm->rdsize);
1778  fsm->wrsize = 16 * BUFSIZ;
1779  fsm->wrbuf = fsm->wrb = (char *) xmalloc(fsm->wrsize);
1780  }
1781 
1782  fsm->mkdirsdone = 0;
1783  fsm->ix = -1;
1784  fsm->links = NULL;
1785  fsm->li = NULL;
1786  errno = 0; /* XXX get rid of EBADF */
1787 
1788  /* Detect and create directories not explicitly in package. */
1789  if (fsm->goal == IOSM_PKGINSTALL) {
1790 /*@-compdef@*/
1791  rc = fsmNext(fsm, IOSM_MKDIRS);
1792 /*@=compdef@*/
1793  if (!rc) fsm->mkdirsdone = 1;
1794  }
1795 
1796  break;
1797  case IOSM_INIT:
1798  fsm->path = _free(fsm->path);
1799  fsm->lpath = _free(fsm->lpath);
1800  fsm->postpone = 0;
1801  fsm->diskchecked = fsm->exists = 0;
1802  fsm->subdir = NULL;
1803  fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL);
1804  fsm->action = FA_UNKNOWN;
1805  fsm->osuffix = NULL;
1806  fsm->nsuffix = NULL;
1807 
1808  if (fsm->goal == IOSM_PKGINSTALL) {
1809  /* Read next header from payload, checking for end-of-payload. */
1810  rc = fsmUNSAFE(fsm, IOSM_NEXT);
1811  }
1812  if (rc) break;
1813 
1814  /* Identify mapping index. */
1815  fsm->ix = ((fsm->goal == IOSM_PKGINSTALL)
1816  ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter));
1817 
1818 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST)) {
1819  /* Detect end-of-loop and/or mapping error. */
1820 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) {
1821  if (fsm->ix < 0) {
1822  if (fsm->goal == IOSM_PKGINSTALL) {
1823 #if 0
1825  _("archive file %s was not found in header file list\n"),
1826  fsm->path);
1827 #endif
1828  if (fsm->failedFile && *fsm->failedFile == NULL)
1829  *fsm->failedFile = xstrdup(fsm->path);
1830  rc = IOSMERR_UNMAPPED_FILE;
1831  } else {
1832  rc = IOSMERR_HDR_TRAILER;
1833  }
1834  break;
1835  }
1836 }
1837 
1838  /* On non-install, mode must be known so that dirs don't get suffix. */
1839  if (fsm->goal != IOSM_PKGINSTALL) {
1840  rpmfi fi = fsmGetFi(fsm);
1841  st->st_mode = fi->fmodes[fsm->ix];
1842  }
1843 }
1844 
1845  /* Generate file path. */
1846  rc = fsmNext(fsm, IOSM_MAP);
1847  if (rc) break;
1848 
1849  /* Perform lstat/stat for disk file. */
1850 #ifdef NOTYET
1851  rc = fsmStat(fsm);
1852 #else
1853  if (fsm->path != NULL &&
1854  !(fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))
1855  {
1856  rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1857  ? IOSM_LSTAT : IOSM_STAT));
1858  if (rc == IOSMERR_ENOENT) {
1859  errno = saveerrno;
1860  rc = 0;
1861  fsm->exists = 0;
1862  } else if (rc == 0) {
1863  fsm->exists = 1;
1864  }
1865  } else {
1866  /* Skip %ghost files on build. */
1867  fsm->exists = 0;
1868  }
1869 #endif
1870  fsm->diskchecked = 1;
1871  if (rc) break;
1872 
1873  /* On non-install, the disk file stat is what's remapped. */
1874  if (fsm->goal != IOSM_PKGINSTALL)
1875  *st = *ost; /* structure assignment */
1876 
1877  /* Remap file perms, owner, and group. */
1878  rc = fsmMapAttrs(fsm);
1879  if (rc) break;
1880 
1881  fsm->postpone = iosmFileActionSkipped(fsm->action);
1882  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
1883  /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */
1884  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1885  fsm->postpone = saveHardLink(fsm);
1886  if (fsm->postpone < 0) {
1887  rc = RPMRC_FAIL;
1888  break;
1889  }
1890  }
1891  /*@=evalorder@*/
1892  }
1893 if (fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST) fsm->postpone = 1;
1894  break;
1895  case IOSM_PRE:
1896  break;
1897  case IOSM_MAP:
1898  rc = fsmMapPath(fsm);
1899  break;
1900  case IOSM_MKDIRS:
1901  rc = fsmMkdirs(fsm);
1902  break;
1903  case IOSM_RMDIRS:
1904  if (fsm->dnlx)
1905  rc = fsmRmdirs(fsm);
1906  break;
1907  case IOSM_PROCESS:
1908  if (fsm->postpone) {
1909  if (fsm->goal == IOSM_PKGINSTALL) {
1910  /* XXX Skip over file body, archive headers already done. */
1911  if (S_ISREG(st->st_mode))
1912  rc = fsmNext(fsm, IOSM_EAT);
1913  }
1914  break;
1915  }
1916 
1917  if (fsm->goal == IOSM_PKGBUILD) {
1918  if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
1919  break;
1920  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1921  struct hardLink_s * li, * prev;
1922 
1923 if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) break;
1924  rc = writeLinkedFile(fsm);
1925  if (rc) break; /* W2DO? */
1926 
1927  for (li = fsm->links, prev = NULL; li; prev = li, li = li->next)
1928  if (li == fsm->li)
1929  /*@loopbreak@*/ break;
1930 
1931  if (prev == NULL)
1932  fsm->links = fsm->li->next;
1933  else
1934  prev->next = fsm->li->next;
1935  fsm->li->next = NULL;
1936  fsm->li = freeHardLink(fsm->li);
1937  } else {
1938  rc = writeFile(fsm, 1);
1939  }
1940  break;
1941  }
1942 
1943  if (fsm->goal != IOSM_PKGINSTALL)
1944  break;
1945 
1946  if (S_ISREG(st->st_mode) && fsm->lpath != NULL) {
1947  const char * opath = fsm->opath;
1948  char * t = (char *) xmalloc(strlen(fsm->lpath+1) + strlen(fsm->suffix) + 1);
1949  (void) stpcpy(t, fsm->lpath+1);
1950  fsm->opath = t;
1951  /* XXX link(fsm->opath, fsm->path) */
1952  rc = fsmNext(fsm, IOSM_LINK);
1953  if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
1954  *fsm->failedFile = xstrdup(fsm->path);
1955  }
1956  fsm->opath = _free(fsm->opath);
1957  fsm->opath = opath;
1958  break; /* XXX so that delayed hard links get skipped. */
1959  }
1960  if (S_ISREG(st->st_mode)) {
1961  const char * path = fsm->path;
1962  if (fsm->osuffix)
1963  fsm->path = fsmFsPath(fsm, st, NULL, NULL);
1964  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1965 
1966  if (rc == 0 && fsm->osuffix) {
1967  const char * opath = fsm->opath;
1968  fsm->opath = fsm->path;
1969  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
1970  rc = fsmNext(fsm, IOSM_RENAME);
1971  if (!rc)
1973  _("%s saved as %s\n"),
1974  (fsm->opath ? fsm->opath : ""),
1975  (fsm->path ? fsm->path : ""));
1976  fsm->path = _free(fsm->path);
1977  fsm->opath = opath;
1978  }
1979 
1980  /*@-dependenttrans@*/
1981  fsm->path = path;
1982  /*@=dependenttrans@*/
1983  if (!(rc == IOSMERR_ENOENT)) return rc;
1984  rc = extractRegular(fsm);
1985  } else if (S_ISDIR(st->st_mode)) {
1986  mode_t st_mode = st->st_mode;
1987  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1988  if (rc == IOSMERR_ENOENT) {
1989  st->st_mode &= ~07777; /* XXX abuse st->st_mode */
1990  st->st_mode |= 00700;
1991  rc = fsmNext(fsm, IOSM_MKDIR);
1992  st->st_mode = st_mode; /* XXX restore st->st_mode */
1993  }
1994  } else if (S_ISLNK(st->st_mode)) {
1995 assert(fsm->lpath != NULL);
1996  /*@=dependenttrans@*/
1997  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
1998  if (rc == IOSMERR_ENOENT)
1999  rc = fsmNext(fsm, IOSM_SYMLINK);
2000  } else if (S_ISFIFO(st->st_mode)) {
2001  mode_t st_mode = st->st_mode;
2002  /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
2003  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
2004  if (rc == IOSMERR_ENOENT) {
2005  st->st_mode = 0000; /* XXX abuse st->st_mode */
2006  rc = fsmNext(fsm, IOSM_MKFIFO);
2007  st->st_mode = st_mode; /* XXX restore st->st_mode */
2008  }
2009  } else if (S_ISCHR(st->st_mode) ||
2010  S_ISBLK(st->st_mode) ||
2011  /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
2012  {
2013  rc = fsmUNSAFE(fsm, IOSM_VERIFY);
2014  if (rc == IOSMERR_ENOENT)
2015  rc = fsmNext(fsm, IOSM_MKNOD);
2016  } else {
2017  /* XXX Repackaged payloads may be missing files. */
2018  if (fsm->repackaged)
2019  break;
2020 
2021  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2022  if (!IS_DEV_LOG(fsm->path))
2024  }
2025  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
2026  fsm->li->createdPath = fsm->li->linkIndex;
2027  rc = fsmMakeLinks(fsm);
2028  }
2029  break;
2030  case IOSM_POST:
2031  break;
2032  case IOSM_MKLINKS:
2033  rc = fsmMakeLinks(fsm);
2034  break;
2035  case IOSM_NOTIFY: /* XXX move from fsm to psm -> tsm */
2036  if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) {
2037  rpmts ts = fsmGetTs(fsm);
2038  rpmfi fi = fsmGetFi(fsm);
2039  void * ptr;
2040  rpmuint64_t archivePos = fdGetCpioPos(fsm->cfd);
2041  if (archivePos > fi->archivePos) {
2042  fi->archivePos = (unsigned long long) archivePos;
2043  ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS,
2044  fi->archivePos, fi->archiveSize);
2045  }
2046  }
2047  break;
2048  case IOSM_UNDO:
2049  if (fsm->postpone)
2050  break;
2051  if (fsm->goal == IOSM_PKGINSTALL) {
2052  /* XXX only erase if temp fn w suffix is in use */
2053  if (fsm->sufbuf[0] != '\0')
2054  (void) fsmNext(fsm,
2055  (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK));
2056 
2057 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
2058  if (fsm->dnlx)
2059  (void) fsmNext(fsm, IOSM_RMDIRS);
2060 #endif
2061  errno = saveerrno;
2062  }
2063  if (fsm->failedFile && *fsm->failedFile == NULL)
2064  *fsm->failedFile = xstrdup(fsm->path);
2065  break;
2066  case IOSM_FINI:
2067  if (!fsm->postpone && fsm->commit) {
2068  if (fsm->goal == IOSM_PKGINSTALL)
2069  rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1)
2070  ? fsmCommitLinks(fsm) : fsmNext(fsm, IOSM_COMMIT));
2071  if (fsm->goal == IOSM_PKGCOMMIT)
2072  rc = fsmNext(fsm, IOSM_COMMIT);
2073  if (fsm->goal == IOSM_PKGERASE)
2074  rc = fsmNext(fsm, IOSM_COMMIT);
2075  }
2076  fsm->path = _free(fsm->path);
2077  fsm->lpath = _free(fsm->lpath);
2078  fsm->opath = _free(fsm->opath);
2079  memset(st, 0, sizeof(*st));
2080  memset(ost, 0, sizeof(*ost));
2081  break;
2082  case IOSM_COMMIT:
2083  /* Rename pre-existing modified or unmanaged file. */
2084  if (fsm->osuffix && fsm->diskchecked &&
2085  (fsm->exists || (fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))))
2086  {
2087  const char * opath = fsm->opath;
2088  const char * path = fsm->path;
2089  fsm->opath = fsmFsPath(fsm, st, NULL, NULL);
2090  fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
2091  rc = fsmNext(fsm, IOSM_RENAME);
2092  if (!rc) {
2093  rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"),
2094  (fsm->opath ? fsm->opath : ""),
2095  (fsm->path ? fsm->path : ""));
2096  }
2097  fsm->path = _free(fsm->path);
2098  fsm->path = path;
2099  fsm->opath = _free(fsm->opath);
2100  fsm->opath = opath;
2101  }
2102 
2103  /* Remove erased files. */
2104  if (fsm->goal == IOSM_PKGERASE) {
2105  if (fsm->action == FA_ERASE) {
2106  rpmfi fi = fsmGetFi(fsm);
2107  if (S_ISDIR(st->st_mode)) {
2108  rc = fsmNext(fsm, IOSM_RMDIR);
2109  if (!rc) break;
2110  switch (rc) {
2111  case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
2112  case IOSMERR_ENOTEMPTY:
2113  /* XXX make sure that build side permits %missingok on directories. */
2114  if (fsm->fflags & RPMFILE_MISSINGOK)
2115  /*@innerbreak@*/ break;
2116 
2117  /* XXX common error message. */
2118  rpmlog(
2120  _("%s rmdir of %s failed: Directory not empty\n"),
2121  rpmfiTypeString(fi), fsm->path);
2122  /*@innerbreak@*/ break;
2123  default:
2124  rpmlog(
2125  (fsm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG),
2126  _("%s rmdir of %s failed: %s\n"),
2127  rpmfiTypeString(fi), fsm->path, strerror(errno));
2128  /*@innerbreak@*/ break;
2129  }
2130  } else {
2131  rc = fsmNext(fsm, IOSM_UNLINK);
2132  if (!rc) break;
2133  switch (rc) {
2134  case IOSMERR_ENOENT:
2135  if (fsm->fflags & RPMFILE_MISSINGOK)
2136  /*@innerbreak@*/ break;
2137  /*@fallthrough@*/
2138  default:
2139  rpmlog(
2141  _(" %s: unlink of %s failed: %s\n"),
2142  rpmfiTypeString(fi), fsm->path, strerror(errno));
2143  /*@innerbreak@*/ break;
2144  }
2145  }
2146  }
2147  /* XXX Failure to remove is not (yet) cause for failure. */
2148  if (!fsm->strict_erasures) rc = 0;
2149  break;
2150  }
2151 
2152  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2153 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) {
2154  if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) {
2155  /* Rename temporary to final file name. */
2156  if (!S_ISDIR(st->st_mode) &&
2157  (fsm->subdir || fsm->suffix || fsm->nsuffix))
2158  {
2159  fsm->opath = fsm->path;
2160  fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix);
2161  rc = fsmNext(fsm, IOSM_RENAME);
2162  if (rc)
2163  (void) Unlink(fsm->opath);
2164  else if (fsm->nsuffix) {
2165  const char * opath = fsmFsPath(fsm, st, NULL, NULL);
2166  rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
2167  (opath ? opath : ""),
2168  (fsm->path ? fsm->path : ""));
2169  opath = _free(opath);
2170  }
2171  fsm->opath = _free(fsm->opath);
2172  }
2173  /*
2174  * Set file security context (if not disabled).
2175  */
2176  if (!rc && !getuid()) {
2177  rc = fsmMapFContext(fsm);
2178  if (!rc)
2179  rc = fsmNext(fsm, IOSM_LSETFCON);
2180 /*@-dependenttrans -observertrans @*/ /* FIX: use the SELinux free wrapper */
2181  fsm->fcontext = _free(fsm->fcontext);
2182 /*@=dependenttrans =observertrans @*/
2183  }
2184  if (S_ISLNK(st->st_mode)) {
2185  if (!rc && !getuid())
2186  rc = fsmNext(fsm, IOSM_LCHOWN);
2187  } else {
2188  if (!rc && !getuid())
2189  rc = fsmNext(fsm, IOSM_CHOWN);
2190  if (!rc)
2191  rc = fsmNext(fsm, IOSM_CHMOD);
2192  if (!rc) {
2193  time_t mtime = st->st_mtime;
2194  rpmfi fi = fsmGetFi(fsm);
2195  if (fi->fmtimes)
2196  st->st_mtime = fi->fmtimes[fsm->ix];
2197  rc = fsmNext(fsm, IOSM_UTIME);
2198  st->st_mtime = mtime;
2199  }
2200  }
2201  }
2202 }
2203 
2204  /* Notify on success. */
2205  if (!rc) rc = fsmNext(fsm, IOSM_NOTIFY);
2206  else if (fsm->failedFile && *fsm->failedFile == NULL) {
2207  *fsm->failedFile = fsm->path;
2208  fsm->path = NULL;
2209  }
2210  break;
2211  case IOSM_DESTROY:
2212  fsm->path = _free(fsm->path);
2213 
2214  /* Check for hard links missing from payload. */
2215  while ((fsm->li = fsm->links) != NULL) {
2216  fsm->links = fsm->li->next;
2217  fsm->li->next = NULL;
2218  if (fsm->goal == IOSM_PKGINSTALL &&
2219  fsm->commit && fsm->li->linksLeft)
2220  {
2221  for (i = 0 ; i < fsm->li->linksLeft; i++) {
2222  if (fsm->li->filex[i] < 0)
2223  /*@innercontinue@*/ continue;
2225  if (fsm->failedFile && *fsm->failedFile == NULL) {
2226  fsm->ix = fsm->li->filex[i];
2227  if (!fsmNext(fsm, IOSM_MAP)) {
2228  *fsm->failedFile = fsm->path;
2229  fsm->path = NULL;
2230  }
2231  }
2232  /*@loopbreak@*/ break;
2233  }
2234  }
2235  if (fsm->goal == IOSM_PKGBUILD &&
2236  (fsm->mapFlags & IOSM_ALL_HARDLINKS))
2237  {
2239  }
2240  fsm->li = freeHardLink(fsm->li);
2241  }
2242  fsm->ldn = _free(fsm->ldn);
2243  fsm->ldnalloc = fsm->ldnlen = 0;
2244  fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
2245  fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
2246  break;
2247  case IOSM_VERIFY:
2248  if (fsm->diskchecked && !fsm->exists) {
2249  rc = IOSMERR_ENOENT;
2250  break;
2251  }
2252  if (S_ISREG(st->st_mode)) {
2253  char * path = (char *) alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
2254  (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
2255  /*
2256  * XXX HP-UX (and other os'es) don't permit unlink on busy
2257  * XXX files.
2258  */
2259  fsm->opath = fsm->path;
2260  fsm->path = path;
2261  rc = fsmNext(fsm, IOSM_RENAME);
2262  if (!rc)
2263  (void) fsmNext(fsm, IOSM_UNLINK);
2264  else
2265  rc = IOSMERR_UNLINK_FAILED;
2266  fsm->path = fsm->opath;
2267  fsm->opath = NULL;
2268  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2269  /*@notreached@*/ break;
2270  } else if (S_ISDIR(st->st_mode)) {
2271  if (S_ISDIR(ost->st_mode)) return 0;
2272  if (S_ISLNK(ost->st_mode)) {
2273  rc = fsmUNSAFE(fsm, IOSM_STAT);
2274  if (rc == IOSMERR_ENOENT) rc = 0;
2275  if (rc) break;
2276  errno = saveerrno;
2277  if (S_ISDIR(ost->st_mode)) return 0;
2278  }
2279  } else if (S_ISLNK(st->st_mode)) {
2280  if (S_ISLNK(ost->st_mode)) {
2281  /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */
2282  rc = fsmUNSAFE(fsm, IOSM_READLINK);
2283  errno = saveerrno;
2284  if (rc) break;
2285  if (!strcmp(fsm->lpath, fsm->rdbuf)) return 0;
2286  }
2287  } else if (S_ISFIFO(st->st_mode)) {
2288  if (S_ISFIFO(ost->st_mode)) return 0;
2289  } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
2290  if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
2291  (ost->st_rdev == st->st_rdev)) return 0;
2292  } else if (S_ISSOCK(st->st_mode)) {
2293  if (S_ISSOCK(ost->st_mode)) return 0;
2294  }
2295  /* XXX shouldn't do this with commit/undo. */
2296  rc = 0;
2297  if (fsm->stage == IOSM_PROCESS) rc = fsmNext(fsm, IOSM_UNLINK);
2298  if (rc == 0) rc = IOSMERR_ENOENT;
2299  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2300  /*@notreached@*/ break;
2301 
2302  case IOSM_UNLINK:
2303  { const char * fn = fsm->path;
2304  uint8_t * b = (uint8_t *)"";
2305  size_t blen = 0;
2306  uint8_t * d = NULL;
2307  size_t dlen = 0;
2308  uint32_t dalgo = 0;
2309  FD_t fd = NULL;
2310  struct stat sb;
2311  mode_t mode;
2312  sb.st_mode = 0;
2313  if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) {
2314  fd = Fopen(fn, "r.fdio");
2315  blen = sb.st_size;
2316  b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0);
2317  }
2318  mode = sb.st_mode;
2319  rc = rpmlioUnlink(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo);
2320  if (fd != NULL) {
2321 /*@-observertrans@*/ /* FIX: b should be initialized to NULL, not "" */
2322  (void)munmap(b, blen);
2323 /*@=observertrans@*/
2324  (void) Fclose(fd);
2325  fd = NULL;
2326  }
2327  } goto iosmcall;
2328  case IOSM_RENAME:
2329  { const char * ofn = fsm->opath;
2330  const char * fn = fsm->path;
2331  uint8_t * b = NULL;
2332  size_t blen = 0;
2333  uint8_t * d = NULL;
2334  size_t dlen = 0;
2335  uint32_t dalgo = 0;
2336  FD_t fd = NULL;
2337  struct stat sb;
2338  mode_t mode;
2339  sb.st_mode = 0;
2340  if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) {
2341  fd = Fopen(fn, "r.fdio");
2342  blen = sb.st_size;
2343  b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0);
2344  }
2345  mode = sb.st_mode;
2346  rc = rpmlioRename(rpmtsGetRdb(fsmGetTs(fsm)), ofn, fn, mode, b, blen, d, dlen, dalgo);
2347  if (fd != NULL) {
2348  (void)munmap(b, blen);
2349  (void) Fclose(fd);
2350  fd = NULL;
2351  }
2352  } goto iosmcall;
2353  case IOSM_MKDIR:
2354  rc = rpmlioMkdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2355  goto iosmcall;
2356  case IOSM_RMDIR:
2357  rc = rpmlioRmdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2358  goto iosmcall;
2359  case IOSM_LSETFCON:
2360  /* Log iff lsetfilecon() will actually be called. */
2361  if (fsm->fcontext && *fsm->fcontext
2362  && strcmp(fsm->fcontext, "<<none>>"))
2363  rc = rpmlioLsetfilecon(rpmtsGetRdb(fsmGetTs(fsm)),
2364  fsm->path, fsm->fcontext);
2365  goto iosmcall;
2366  case IOSM_CHOWN:
2367  rc = rpmlioChown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid);
2368  goto iosmcall;
2369  case IOSM_LCHOWN:
2370  rc = rpmlioLchown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid);
2371  goto iosmcall;
2372  case IOSM_CHMOD:
2373  rc = rpmlioChmod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2374  goto iosmcall;
2375  case IOSM_UTIME:
2376  rc = rpmlioUtime(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mtime, st->st_mtime);
2377  goto iosmcall;
2378  case IOSM_SYMLINK:
2379  rc = rpmlioSymlink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->lpath, fsm->path);
2380  goto iosmcall;
2381  case IOSM_LINK:
2382  rc = rpmlioLink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->opath, fsm->path);
2383  goto iosmcall;
2384  case IOSM_MKFIFO:
2385  rc = rpmlioMkfifo(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode);
2386  goto iosmcall;
2387  case IOSM_MKNOD:
2388  rc = rpmlioMknod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode, st->st_rdev);
2389  goto iosmcall;
2390  case IOSM_LSTAT:
2391  case IOSM_STAT:
2392  case IOSM_READLINK:
2393  case IOSM_CHROOT:
2394 iosmcall:
2395  rc = iosmStage(fsm, stage);
2396  break;
2397 
2398  case IOSM_NEXT:
2399  case IOSM_EAT:
2400  case IOSM_POS:
2401  case IOSM_PAD:
2402  case IOSM_TRAILER:
2403  case IOSM_HREAD:
2404  case IOSM_HWRITE:
2405  case IOSM_DREAD:
2406  case IOSM_DWRITE:
2407  rc = iosmStage(fsm, stage);
2408  break;
2409 
2410  case IOSM_ROPEN:
2411  case IOSM_READ:
2412  case IOSM_RCLOSE:
2413  rc = iosmStage(fsm, stage);
2414  break;
2415  case IOSM_WOPEN:
2416  case IOSM_WRITE:
2417  case IOSM_WCLOSE:
2418  rc = iosmStage(fsm, stage);
2419  break;
2420 
2421  default:
2422  break;
2423  }
2424 
2425  if (!(stage & IOSM_INTERNAL)) {
2426  fsm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc);
2427  }
2428  return rc;
2429 }
2430 /*@=compmempass@*/
int arHeaderRead(void *_iosm, struct stat *st)
Read ar(1) header.
Definition: ar.c:92
static const char * suffix[]
Definition: rpmgrep.c:188
Definition: iosm.h:34
struct hardLink_s * li
Definition: iosm.h:250
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:546
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:1291
const char * nsuffix
Definition: iosm.h:262
const char ** failedFile
Definition: iosm.h:254
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:979
Structures used for an "rpmte" transaction element.
int commit
Definition: iosm.h:278
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
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:2833
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:610
size_t wrsize
Definition: iosm.h:241
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2916
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
int(* headerRead)(void *_iosm, struct stat *st)
Definition: iosm.h:309
static int fsmMkdirs(IOSM_t fsm)
Create (if necessary) directories not explicitly included in package.
Definition: fsm.c:1442
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
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:614
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 cpioHeaderWrite(void *_iosm, struct stat *st)
Write cpio header.
Definition: cpio.c:225
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
#define SUFFIX_RPMSAVE
Definition: fsm.c:97
size_t wrnb
Definition: iosm.h:243
char * alloca()
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:25
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:301
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
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:1601
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:78
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:26
iosmMapFlags mapFlags
Definition: iosm.h:286
int iosmFileActionSkipped(iosmFileAction action)
Is the file going to be skipped?
Definition: iosm.c:2672
Structures used for tar(1) archives.
#define SUFFIX_RPMORIG
Definition: fsm.c:96
Definition: iosm.h:160
const char * fcontext
Definition: iosm.h:298
#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:898
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
int(* trailerWrite)(void *_iosm)
Definition: iosm.h:313
size_t rdlen
Definition: iosm.h:234
static int fsmMakeLinks(IOSM_t fsm)
Create pending hard links to existing file.
Definition: fsm.c:1282
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:1632
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(* headerWrite)(void *_iosm, struct stat *st)
Definition: iosm.h:311
int fsmTeardown(void *_fsm)
Clean file state machine.
Definition: fsm.c:756
static int writeLinkedFile(IOSM_t fsm)
Write set of linked files to payload stream.
Definition: fsm.c:1208
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 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:31
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:429
rpmfi rpmfiLink(rpmfi fi, const char *msg)
Reference a file info set instance.
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:1343
char * stpcpy(char *dest, const char *src)
#define IOSM_INTERNAL
Definition: iosm.h:106
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:556
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:1073
const char * iosmFileStageString(iosmFileStage a)
Return formatted string representation of file stages.
Definition: iosm.c:2697
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
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
#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:807
#define IS_DEV_LOG(_x)
Definition: fsm.c:1594
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:632
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:562
static int arSetup(IOSM_t iosm, rpmfi fi)
Definition: iosm.c:596
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:2991
#define _(Text)
Definition: system.h:30
int diskchecked
Definition: iosm.h:273
#define xmalloc
Definition: system.h:33
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1022
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:485
int exists
Definition: iosm.h:274
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:1344
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:1387
static int fsmMapFContext(IOSM_t fsm)
Definition: fsm.c:788
#define xrealloc
Definition: system.h:36
#define _fafilter(_a)
File name and stat information.
Definition: iosm.h:218
size_t ldnalloc
Definition: iosm.h:271
Definition: iosm.h:33
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397
const char * opath
Definition: iosm.h:224