rpm  5.4.14
iosm.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 <ugid.h> /* XXX unameToUid() and gnameToGid() */
11 
12 #include <rpmsq.h> /* XXX rpmsqJoin()/rpmsqThread() */
13 #include <rpmsw.h> /* XXX rpmswAdd() */
14 #include <rpmsx.h>
15 
16 #include "../rpmdb/rpmtag.h"
17 
18 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmts_s * rpmts;
19 typedef /*@abstract@*/ struct rpmte_s * rpmte;
20 
21 #define _IOSM_INTERNAL
22 #include <iosm.h>
23 #define iosmUNSAFE iosmStage
24 
25 #include "cpio.h"
26 #include "tar.h"
27 #include "ar.h"
28 
30 #define _RPMFI_INTERNAL
31 #define _RPMFI_NOMETHODS
32 #include "../lib/rpmfi.h"
33 
34 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmds_s * rpmds;
35 typedef struct rpmRelocation_s * rpmRelocation;
36 #undef _USE_RPMTE
37 #if defined(_USE_RPMTE)
38 typedef /*@abstract@*/ void * alKey;
39 #include "rpmte.h"
40 #endif
41 
42 #undef _USE_RPMSX
43 #if defined(_USE_RPMSX)
44 #include "../lib/rpmsx.h" /* XXX rpmsx rpmsxFContext rpmsxFree */
45 #endif
46 
47 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmdb_s * rpmdb;
48 typedef /*@abstract@*/ struct rpmmi_s * rpmmi;
49 typedef struct rpmPRCO_s * rpmPRCO;
50 typedef struct Spec_s * Spec;
51 #undef _USE_RPMTS
52 #if defined(_USE_RPMTS)
53 #include "rpmts.h"
54 #endif
55 
56 #include "debug.h"
57 
58 /*@access FD_t @*/ /* XXX void ptr args */
59 /*@access IOSMI_t @*/
60 /*@access IOSM_t @*/
61 
62 /*@access rpmfi @*/
63 
64 #ifdef __cplusplus
65 GENfree(unsigned short *)
66 GENfree(int *)
67 GENfree(IOSM_t)
68 GENfree(iosmFileAction *)
69 #endif /* __cplusplus */
70 
71 #define alloca_strdup(_s) strcpy((char *)alloca(strlen(_s)+1), (_s))
72 
73 #define _IOSM_DEBUG 0
74 /*@unchecked@*/
76 
77 /*@-exportheadervar@*/
78 /*@unchecked@*/
79 int _iosm_threads = 0;
80 /*@=exportheadervar@*/
81 
82 /*@-redecl@*/
83 int (*_iosmNext) (IOSM_t iosm, iosmFileStage nstage)
84  /*@modifies iosm @*/ = &iosmNext;
85 /*@=redecl@*/
86 
87 #if defined(_USE_RPMTS)
88 void * iosmGetTs(const IOSM_t iosm)
89 {
90  const IOSMI_t iter = iosm->iter;
91  /*@-compdef -refcounttrans -retexpose -usereleased @*/
92  return (iter ? iter->ts : NULL);
93  /*@=compdef =refcounttrans =retexpose =usereleased @*/
94 }
95 #endif
96 
97 void * iosmGetFi(const IOSM_t iosm)
98 {
99  const IOSMI_t iter = iosm->iter;
100  /*@-compdef -refcounttrans -retexpose -usereleased @*/
101  return (iter ? iter->fi : NULL);
102  /*@=compdef =refcounttrans =retexpose =usereleased @*/
103 }
104 
105 #define SUFFIX_RPMORIG ".rpmorig"
106 #define SUFFIX_RPMSAVE ".rpmsave"
107 #define SUFFIX_RPMNEW ".rpmnew"
108 
117 static /*@only@*//*@null@*/
118 const char * iosmFsPath(/*@special@*/ /*@null@*/ const IOSM_t iosm,
119  /*@null@*/ const struct stat * st,
120  /*@null@*/ const char * subdir,
121  /*@null@*/ const char * suffix)
122  /*@uses iosm->dirName, iosm->baseName */
123  /*@*/
124 {
125  const char * s = NULL;
126 
127  if (iosm) {
128  char * t;
129  int nb;
130  nb = strlen(iosm->dirName) +
131  (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) +
132  (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) +
133  strlen(iosm->baseName) + 1;
134  s = t = (char *) xmalloc(nb);
135  t = stpcpy(t, iosm->dirName);
136  if (st && !S_ISDIR(st->st_mode))
137  if (subdir) t = stpcpy(t, subdir);
138  t = stpcpy(t, iosm->baseName);
139  if (st && !S_ISDIR(st->st_mode))
140  if (suffix) t = stpcpy(t, suffix);
141  }
142  return s;
143 }
144 
150 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * _iter)
151  /*@modifies p @*/
152 {
153  IOSMI_t iter = (IOSMI_t) _iter;
154  if (iter) {
155 #if !defined(_RPMFI_NOMETHODS)
156  iter->fi = rpmfiUnlink(iter->fi, "mapIterator");
157 #endif
158  iter->fi = NULL;
159  }
160  return _free(iter);
161 }
162 
169 /*@-mustmod@*/
170 static void *
171 mapInitIterator(rpmfi fi, int reverse)
172  /*@modifies fi @*/
173 {
174  IOSMI_t iter = NULL;
175 
176  iter = (IOSMI_t) xcalloc(1, sizeof(*iter));
177 #if !defined(_RPMFI_NOMETHODS)
178  iter->fi = rpmfiLink(fi, "mapIterator");
179 #else
180 /*@i@*/ iter->fi = fi;
181 #endif
182  iter->reverse = reverse;
183  iter->i = (iter->reverse ? (fi->fc - 1) : 0);
184  iter->isave = iter->i;
185  return iter;
186 }
187 /*@=mustmod@*/
188 
194 static int mapNextIterator(/*@null@*/ void * _iter)
195  /*@*/
196 {
197  IOSMI_t iter = (IOSMI_t) _iter;
198  int i = -1;
199 
200  if (iter) {
201  if (iter->reverse) {
202  if (iter->i >= 0) i = iter->i--;
203  } else {
204  if (iter->i < (int) ((rpmfi)iter->fi)->fc) i = iter->i++;
205  }
206  iter->isave = i;
207  }
208  return i;
209 }
210 
213 static int iosmStrCmp(const void * a, const void * b)
214  /*@*/
215 {
216  const char * aurl = *(const char **)a;
217  const char * burl = *(const char **)b;
218  const char * afn = NULL;
219  const char * bfn = NULL;
220 
221  (void) urlPath(aurl, &afn);
222  (void) urlPath(burl, &bfn);
223 
224 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES
225  /* XXX Some rpm-2.4 packages from 1997 have basename only in payloads. */
226  if (strchr(afn, '/') == NULL)
227  bfn = strrchr(bfn, '/') + 1;
228 #endif
229 
230  /* Match rpm-4.0 payloads with ./ prefixes. */
231  if (afn[0] == '.' && afn[1] == '/') afn += 2;
232  if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
233 
234  /* If either path is absolute, make it relative to '/'. */
235  if (afn[0] == '/') afn += 1;
236  if (bfn[0] == '/') bfn += 1;
237 
238  return strcmp(afn, bfn);
239 }
240 
247 static int mapFind(/*@null@*/ IOSMI_t iter, const char * iosmPath)
248  /*@modifies iter @*/
249 {
250  int ix = -1;
251 
252  if (iter) {
253 /*@-onlytrans@*/
254  const rpmfi fi = (rpmfi) iter->fi;
255 /*@=onlytrans@*/
256 #if !defined(_RPMFI_NOMETHODS)
257  size_t fc = rpmfiFC(fi);
258 #else
259  size_t fc = (fi ? fi->fc : 0);
260 #endif
261  if (fi && fc > 0 && fi->apath && iosmPath && *iosmPath) {
262  const char ** p = NULL;
263 
264  if (fi->apath != NULL)
265  p = (const char **)
266  bsearch(&iosmPath, fi->apath, fc, sizeof(iosmPath),
267  iosmStrCmp);
268  if (p) {
269  iter->i = p - fi->apath;
270  ix = mapNextIterator(iter);
271  }
272  }
273  }
274  return ix;
275 }
276 
280 typedef struct dnli_s {
281  rpmfi fi;
282 /*@only@*/ /*@null@*/
283  char * active;
284  int reverse;
285  int isave;
286  int i;
287 } * DNLI_t;
288 
294 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * _dnli)
295  /*@modifies _dnli @*/
296 {
297  if (_dnli) {
298  DNLI_t dnli = (DNLI_t)_dnli;
299  if (dnli->active) free(dnli->active);
300  }
301  return _free((void *)_dnli);
302 }
303 
306 static inline int dnlCount(/*@null@*/ const DNLI_t dnli)
307  /*@*/
308 {
309  return (int) (dnli ? dnli->fi->dc : 0);
310 }
311 
314 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli)
315  /*@*/
316 {
317  return (dnli ? dnli->isave : -1);
318 }
319 
326 /*@-usereleased@*/
327 static /*@only@*/ /*@null@*/
328 void * dnlInitIterator(/*@special@*/ const IOSM_t iosm,
329  int reverse)
330  /*@uses iosm->iter @*/
331  /*@*/
332 {
333  rpmfi fi = (rpmfi) iosmGetFi(iosm);
334  const char * dnl;
335  DNLI_t dnli;
336  int i, j;
337 
338  if (fi == NULL)
339  return NULL;
340  dnli = (DNLI_t) xcalloc(1, sizeof(*dnli));
341  dnli->fi = fi;
342  dnli->reverse = reverse;
343  dnli->i = (int) (reverse ? fi->dc : 0);
344 
345  if (fi->dc) {
346  dnli->active = (char *) xcalloc(fi->dc, sizeof(*dnli->active));
347 
348  /* Identify parent directories not skipped. */
349 #if !defined(_RPMFI_NOMETHODS)
350  if ((fi = rpmfiInit(fi, 0)) != NULL)
351  while ((i = rpmfiNext(fi)) >= 0)
352 #else
353  for (i = 0; i < (int)fi->fc; i++)
354 #endif
355  {
356  if (!iosmFileActionSkipped((iosmFileAction)fi->actions[i]))
357  dnli->active[fi->dil[i]] = (char)1;
358  }
359 
360  /* Exclude parent directories that are explicitly included. */
361 #if !defined(_RPMFI_NOMETHODS)
362  if ((fi = rpmfiInit(fi, 0)) != NULL)
363  while ((i = rpmfiNext(fi)) >= 0)
364 #else
365  for (i = 0; i < (int)fi->fc; i++)
366 #endif
367  {
368  rpmuint32_t dil;
369  size_t dnlen, bnlen;
370 
371  if (!S_ISDIR(fi->fmodes[i]))
372  continue;
373 
374  dil = fi->dil[i];
375  dnlen = strlen(fi->dnl[dil]);
376  bnlen = strlen(fi->bnl[i]);
377 
378  for (j = 0; j < (int)fi->dc; j++) {
379  size_t jlen;
380 
381  if (!dnli->active[j] || j == (int)dil)
382  /*@innercontinue@*/ continue;
383  (void) urlPath(fi->dnl[j], &dnl);
384  jlen = strlen(dnl);
385  if (jlen != (dnlen+bnlen+1))
386  /*@innercontinue@*/ continue;
387  if (strncmp(dnl, fi->dnl[dil], dnlen))
388  /*@innercontinue@*/ continue;
389  if (strncmp(dnl+dnlen, fi->bnl[i], bnlen))
390  /*@innercontinue@*/ continue;
391  if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
392  /*@innercontinue@*/ continue;
393  /* This directory is included in the package. */
394  dnli->active[j] = (char)0;
395  /*@innerbreak@*/ break;
396  }
397  }
398 
399  /* Print only once per package. */
400  if (!reverse) {
401  j = 0;
402  for (i = 0; i < (int)fi->dc; i++) {
403  if (!dnli->active[i]) continue;
404  if (j == 0) {
405  j = 1;
407  D_("========== Directories not explicitly included in package:\n"));
408  }
409  (void) urlPath(fi->dnl[i], &dnl);
410  rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, dnl);
411  }
412  if (j)
413  rpmlog(RPMLOG_DEBUG, "==========\n");
414  }
415  }
416  return dnli;
417 }
418 /*@=usereleased@*/
419 
425 static /*@observer@*/ /*@null@*/
426 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli)
427  /*@modifies dnli @*/
428 {
429  const char * dn = NULL;
430 
431  if (dnli) {
432  rpmfi fi = dnli->fi;
433  int i = -1;
434 
435  if (dnli->active)
436  do {
437  i = (!dnli->reverse ? dnli->i++ : --dnli->i);
438  } while (i >= 0 && i < (int)fi->dc && !dnli->active[i]);
439 
440  if (i >= 0 && i < (int)fi->dc)
441  dn = fi->dnl[i];
442  else
443  i = -1;
444  dnli->isave = i;
445  }
446  return dn;
447 }
448 
449 #if defined(WITH_PTHREADS)
450 static void * iosmThread(void * _iosm)
451  /*@globals h_errno, fileSystem, internalState @*/
452  /*@modifies _iosm, fileSystem, internalState @*/
453 {
454  IOSM_t iosm = (IOSM_t) _iosm;
455 /*@-unqualifiedtrans@*/
456  return ((void *) ((long)iosmStage(iosm, iosm->nstage)));
457 /*@=unqualifiedtrans@*/
458 }
459 #endif
460 
461 int iosmNext(IOSM_t iosm, iosmFileStage nstage)
462  /*@globals h_errno, fileSystem, internalState @*/
463  /*@modifies iosm, fileSystem, internalState @*/
464 {
465  iosm->nstage = nstage;
466 #if defined(WITH_PTHREADS)
467  if (iosm->multithreaded)
468  return rpmsqJoin( rpmsqThread(iosmThread, iosm) );
469 #endif
470  return iosmStage(iosm, iosm->nstage);
471 }
472 
478 static int saveHardLink(/*@special@*/ /*@partial@*/ IOSM_t iosm)
479  /*@uses iosm->links, iosm->ix, iosm->sb, iosm->goal, iosm->nsuffix @*/
480  /*@defines iosm->li @*/
481  /*@releases iosm->path @*/
482  /*@globals h_errno, fileSystem, internalState @*/
483  /*@modifies iosm, fileSystem, internalState @*/
484 {
485  struct stat * st = &iosm->sb;
486  int rc = 0;
487  int ix = -1;
488  int j;
489 
490  /* Find hard link set. */
491  for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li->next) {
492  if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == st->st_dev)
493  break;
494  }
495 
496  /* New hard link encountered, add new link to set. */
497  if (iosm->li == NULL) {
498  iosm->li = (struct hardLink_s *) xcalloc(1, sizeof(*iosm->li));
499  iosm->li->next = NULL;
500  iosm->li->sb = *st; /* structure assignment */
501  iosm->li->nlink = (int) st->st_nlink;
502  iosm->li->linkIndex = iosm->ix;
503  iosm->li->createdPath = -1;
504 
505  iosm->li->filex = (int *) xcalloc(st->st_nlink, sizeof(iosm->li->filex[0]));
506  memset(iosm->li->filex, -1, (st->st_nlink * sizeof(iosm->li->filex[0])));
507  iosm->li->nsuffix = (const char **) xcalloc(st->st_nlink, sizeof(*iosm->li->nsuffix));
508 
509  if (iosm->goal == IOSM_PKGBUILD)
510  iosm->li->linksLeft = (int) st->st_nlink;
511  if (iosm->goal == IOSM_PKGINSTALL)
512  iosm->li->linksLeft = 0;
513 
514  /*@-kepttrans@*/
515  iosm->li->next = iosm->links;
516  /*@=kepttrans@*/
517  iosm->links = iosm->li;
518  }
519 
520  if (iosm->goal == IOSM_PKGBUILD) --iosm->li->linksLeft;
521  iosm->li->filex[iosm->li->linksLeft] = iosm->ix;
522  /*@-observertrans -dependenttrans@*/
523  iosm->li->nsuffix[iosm->li->linksLeft] = iosm->nsuffix;
524  /*@=observertrans =dependenttrans@*/
525  if (iosm->goal == IOSM_PKGINSTALL) iosm->li->linksLeft++;
526 
527  if (iosm->goal == IOSM_PKGBUILD)
528  return (iosm->li->linksLeft > 0);
529 
530  if (iosm->goal != IOSM_PKGINSTALL)
531  return 0;
532 
533  if (!(st->st_size || iosm->li->linksLeft == (int) st->st_nlink))
534  return 1;
535 
536  /* Here come the bits, time to choose a non-skipped file name. */
537  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
538 
539  for (j = iosm->li->linksLeft - 1; j >= 0; j--) {
540  ix = iosm->li->filex[j];
541  if (ix < 0 || iosmFileActionSkipped((iosmFileAction)fi->actions[ix]))
542  continue;
543  break;
544  }
545  }
546 
547  /* Are all links skipped or not encountered yet? */
548  if (ix < 0 || j < 0)
549  return 1; /* XXX W2DO? */
550 
551  /* Save the non-skipped file name and map index. */
552  iosm->li->linkIndex = j;
553  iosm->path = _free(iosm->path);
554  iosm->ix = ix;
555  rc = iosmNext(iosm, IOSM_MAP);
556  return rc;
557 }
558 
564 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li)
565  /*@modifies li @*/
566 {
567  if (li) {
568  li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */
569  li->filex = _free(li->filex);
570  }
571  return _free(li);
572 }
573 
575 {
576  IOSM_t iosm = (IOSM_t) xcalloc(1, sizeof(*iosm));
577  return iosm;
578 }
579 
581 {
582  if (iosm) {
583  iosm->path = _free(iosm->path);
584  while ((iosm->li = iosm->links) != NULL) {
585  iosm->links = iosm->li->next;
586  iosm->li->next = NULL;
587  iosm->li = (struct hardLink_s *) freeHardLink((struct hardLink_s *) iosm->li);
588  }
589  iosm->dnlx = _free(iosm->dnlx);
590  iosm->ldn = _free(iosm->ldn);
591  iosm->iter = (IOSMI_t) mapFreeIterator((IOSMI_t)iosm->iter);
592  }
593  return _free(iosm);
594 }
595 
596 static int arSetup(IOSM_t iosm, rpmfi fi)
597  /*@modifies iosm @*/
598 {
599  const char * path;
600  char * t;
601  size_t lmtablen = 0;
602  size_t nb;
603 
604  /* Calculate size of ar(1) long member table. */
605 #if !defined(_RPMFI_NOMETHODS)
606  if ((fi = rpmfiInit(fi, 0)) != NULL)
607  while (rpmfiNext(fi) >= 0)
608 #else
609  int i;
610  if (fi != NULL)
611  for (i = 0; i < (int)fi->fc; i++)
612 #endif
613  {
614 #ifdef NOTYET
615  if (fi->apath) {
616  const char * apath = NULL;
617  (void) urlPath(fi->apath[ix], &apath);
618  path = apath + fi->striplen;
619  } else
620 #endif
621 #if !defined(_RPMFI_NOMETHODS)
622  path = rpmfiBN(fi);
623 #else
624  path = fi->bnl[i];
625 #endif
626  if ((nb = strlen(path)) < 15)
627  continue;
628  lmtablen += nb + 1; /* trailing \n */
629  }
630 
631  /* Anything to do? */
632  if (lmtablen == 0)
633  return 0;
634 
635  /* Create and load ar(1) long member table. */
636  iosm->lmtab = t = (char *) xmalloc(lmtablen + 1); /* trailing \0 */
637  iosm->lmtablen = lmtablen;
638  iosm->lmtaboff = 0;
639 #if !defined(_RPMFI_NOMETHODS)
640  if ((fi = rpmfiInit(fi, 0)) != NULL)
641  while (rpmfiNext(fi) >= 0)
642 #else
643  if (fi != NULL)
644  for (i = 0; i < (int)fi->fc; i++)
645 #endif
646  {
647 #ifdef NOTYET
648  if (fi->apath) {
649  const char * apath = NULL;
650  (void) urlPath(fi->apath[ix], &apath);
651  path = apath + fi->striplen;
652  } else
653 #endif
654 #if !defined(_RPMFI_NOMETHODS)
655  path = rpmfiBN(fi);
656 #else
657  path = fi->bnl[i];
658 #endif
659  if ((nb = strlen(path)) < 15)
660  continue;
661  t = stpcpy(t, path);
662  *t++ = '\n';
663  }
664  *t = '\0';
665 
666  return 0;
667 }
668 
669 int iosmSetup(IOSM_t iosm, iosmFileStage goal, const char * afmt,
670  const void * _ts, const void * _fi, FD_t cfd,
671  unsigned int * archiveSize, const char ** failedFile)
672 {
673 #if defined(_USE_RPMTS)
674  const rpmts ts = (const rpmts) _ts;
675 #endif
676 /*@i@*/ const rpmfi fi = (const rpmfi) _fi;
677 #if defined(_USE_RPMTE)
678  int reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT);
679  int adding = (rpmteType(fi->te) == TR_ADDED);
680 #else
681  int reverse = 0; /* XXX HACK: devise alternative means */
682  int adding = 1; /* XXX HACK: devise alternative means */
683 #endif
684  size_t pos = 0;
685  int rc, ec = 0;
686 
687  iosm->debug = _iosm_debug;
689  iosm->adding = adding;
690 
691 /*@+voidabstract -nullpass@*/
692 if (iosm->debug < 0)
693 fprintf(stderr, "--> iosmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", iosm, goal, afmt, (void *)_ts, _fi, cfd, archiveSize, failedFile);
694 /*@=voidabstract =nullpass@*/
695 
696  _iosmNext = &iosmNext;
697  if (iosm->headerRead == NULL) {
698  if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) {
699 if (iosm->debug < 0)
700 fprintf(stderr, "\ttar vectors set\n");
701  iosm->headerRead = &tarHeaderRead;
702  iosm->headerWrite = &tarHeaderWrite;
703  iosm->trailerWrite = &tarTrailerWrite;
704  iosm->blksize = TAR_BLOCK_SIZE;
705  } else
706  if (afmt != NULL && !strcmp(afmt, "ar")) {
707 if (iosm->debug < 0)
708 fprintf(stderr, "\tar vectors set\n");
709  iosm->headerRead = &arHeaderRead;
710  iosm->headerWrite = &arHeaderWrite;
711  iosm->trailerWrite = &arTrailerWrite;
712  iosm->blksize = 2;
713  if (goal == IOSM_PKGBUILD || goal == IOSM_PKGERASE)
714  (void) arSetup(iosm, fi);
715  } else
716  {
717 if (iosm->debug < 0)
718 fprintf(stderr, "\tcpio vectors set\n");
719  iosm->headerRead = &cpioHeaderRead;
720  iosm->headerWrite = &cpioHeaderWrite;
722  iosm->blksize = 4;
723  }
724  }
725 
726  iosm->goal = goal;
727  if (cfd != NULL) {
728 /*@-assignexpose@*/
729  iosm->cfd = fdLink(cfd, "persist (iosm)");
730 /*@=assignexpose@*/
731  pos = fdGetCpioPos(iosm->cfd);
732  fdSetCpioPos(iosm->cfd, 0);
733  }
734 /*@-mods@*/ /* WTF? */
735  iosm->iter = (IOSMI_t) mapInitIterator(fi, reverse);
736 /*@=mods@*/
737 #if defined(_USE_RPMTS)
738  iosm->iter->ts = rpmtsLink(ts, "mapIterator");
740  iosm->nofdigests =
741  (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS))
742  ? 0 : 1;
743 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
744  iosm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) &&
745  iosm->goal != IOSM_PKGCOMMIT) ? 0 : 1);
746 #undef _tsmask
747 #else
748 /*@-assignexpose -temptrans @*/
749  iosm->iter->ts = (void *)_ts;
750 /*@=assignexpose =temptrans @*/
751  iosm->nofcontexts = 1;
752  iosm->nofdigests = 1;
753  iosm->commit = 1;
754 #endif
755 
756 #if defined(_USE_RPMTS)
757  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
758  fi->archivePos = 0;
759  (void) rpmtsNotify(ts, fi->te,
760  RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize);
761  }
762 #endif
763 
764  /*@-assignexpose@*/
765  iosm->archiveSize = archiveSize;
766  if (iosm->archiveSize)
767  *iosm->archiveSize = 0;
768  iosm->failedFile = failedFile;
769  if (iosm->failedFile)
770  *iosm->failedFile = NULL;
771  /*@=assignexpose@*/
772 
773  memset(iosm->sufbuf, 0, sizeof(iosm->sufbuf));
774  if (iosm->goal == IOSM_PKGINSTALL) {
775  rpmuint32_t tid;
776 #if defined(_USE_RPMTS)
777  tid = (ts != NULL ? rpmtsGetTid(ts) : 0);
778 #else
779  static time_t now = 0;
780  if (now == 0) now = time(NULL);
781  tid = (rpmuint32_t) now;
782 #endif
783  if (tid > 0 && tid < 0xffffffff)
784  sprintf(iosm->sufbuf, ";%08x", (unsigned)tid);
785  }
786 
787  ec = iosm->rc = 0;
788  rc = iosmUNSAFE(iosm, IOSM_CREATE);
789  if (rc && !ec) ec = rc;
790 
791  rc = iosmUNSAFE(iosm, iosm->goal);
792  if (rc && !ec) ec = rc;
793 
794  if (iosm->archiveSize && ec == 0)
795  *iosm->archiveSize = (fdGetCpioPos(iosm->cfd) - pos);
796 
797 /*@-nullstate@*/ /* FIX: *iosm->failedFile may be NULL */
798  return ec;
799 /*@=nullstate@*/
800 }
801 
803 {
804  int rc = iosm->rc;
805 
806 if (iosm->debug < 0)
807 fprintf(stderr, "--> iosmTeardown(%p)\n", iosm);
808  if (!rc)
809  rc = iosmUNSAFE(iosm, IOSM_DESTROY);
810 
811  iosm->lmtab = _free(iosm->lmtab);
812 
813  if (iosm->iter != NULL) {
814 #if defined(_USE_RPMTS)
816  &iosm->op_digest);
817  (void)rpmtsFree(iosm->iter->ts);
818 #endif
819  iosm->iter->ts = NULL;
820  mapFreeIterator(iosm->iter); iosm->iter = NULL;
821  }
822  if (iosm->cfd != NULL) {
823  iosm->cfd = fdFree(iosm->cfd, "persist (iosm)");
824  iosm->cfd = NULL;
825  }
826  iosm->failedFile = NULL;
827  return rc;
828 }
829 
830 /*
831  * Set file security context (if not disabled).
832  * @param iosm file state machine data
833  * @return 0 always
834  */
835 static int iosmMapFContext(IOSM_t iosm)
836  /*@modifies iosm @*/
837 {
838  /*
839  * Find file security context (if not disabled).
840  */
841  iosm->fcontext = NULL;
842  if (!iosm->nofcontexts) {
843  iosm->fcontext = rpmsxMatch(NULL, iosm->path, iosm->sb.st_mode);
844 #ifdef DYING /* XXX SELinux file contexts not set from package content. */
845  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
846  int i = iosm->ix;
847 
848  /* Get file security context from package. */
849  if (fi && i >= 0 && i < (int)fi->fc)
850  iosm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL);
851  }
852 #endif
853 /*@=moduncon@*/
854  }
855  return 0;
856 }
857 
859 {
860  rpmfi fi = (rpmfi) iosmGetFi(iosm); /* XXX const except for fstates */
861  int teAdding = iosm->adding;
862  int rc = 0;
863  int i = iosm->ix;
864 
865  iosm->osuffix = NULL;
866  iosm->nsuffix = NULL;
867  iosm->astriplen = 0;
868  iosm->action = FA_UNKNOWN;
869  iosm->mapFlags = (iosmMapFlags) (fi ? fi->mapflags : 0);
870 
871  if (fi && i >= 0 && i < (int)fi->fc) {
872 
873  iosm->astriplen = fi->astriplen;
874  iosm->action = (iosmFileAction) (fi->actions ? fi->actions[i] : fi->action);
875  iosm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags);
876  iosm->mapFlags = (iosmMapFlags) (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
877 
878  /* src rpms have simple base name in payload. */
879  iosm->dirName = fi->dnl[fi->dil[i]];
880  iosm->baseName = fi->bnl[i];
881 
882  switch (iosm->action) {
883  case FA_SKIP:
884  break;
885  case FA_UNKNOWN:
886  break;
887 
888  case FA_COPYOUT:
889  break;
890  case FA_COPYIN:
891  case FA_CREATE:
892 assert(teAdding);
893  break;
894 
895  case FA_SKIPNSTATE:
896  if (fi->fstates && teAdding)
897  fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_NOTINSTALLED;
898  break;
899 
900  case FA_SKIPNETSHARED:
901  if (fi->fstates && teAdding)
902  fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_NETSHARED;
903  break;
904 
905  case FA_SKIPCOLOR:
906  if (fi->fstates && teAdding)
907  fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_WRONGCOLOR;
908  break;
909 
910  case FA_BACKUP:
911  if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
912  iosm->osuffix = (teAdding ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE);
913  break;
914 
915  case FA_ALTNAME:
916 assert(teAdding);
917  if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
918  iosm->nsuffix = SUFFIX_RPMNEW;
919  break;
920 
921  case FA_SAVE:
922 assert(teAdding);
923  if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
924  iosm->osuffix = SUFFIX_RPMSAVE;
925  break;
926  case FA_ERASE:
927 #if 0 /* XXX is this a genhdlist fix? */
928  assert(rpmteType(fi->te) == TR_REMOVED);
929 #endif
930  /*
931  * XXX TODO: %ghost probably shouldn't be removed, but that changes
932  * legacy rpm behavior.
933  */
934  break;
935  default:
936  break;
937  }
938 
939  if ((iosm->mapFlags & IOSM_MAP_PATH) || iosm->nsuffix) {
940  const struct stat * st = &iosm->sb;
941  iosm->path = _free(iosm->path);
942  iosm->path = iosmFsPath(iosm, st, iosm->subdir,
943  (iosm->suffix ? iosm->suffix : iosm->nsuffix));
944  }
945  }
946  return rc;
947 }
948 
950 {
951  struct stat * st = &iosm->sb;
952  rpmfi fi = (rpmfi) iosmGetFi(iosm);
953  int i = iosm->ix;
954 
955  if (fi && i >= 0 && i < (int)fi->fc) {
956  mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
957  mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms);
958  dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0);
959  rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
960  uid_t uid = fi->uid;
961  gid_t gid = fi->gid;
962 
963  /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during
964  installation of _source_ RPMs. Instead, let it use the current
965  run-time owner/group, because most of the time the owner/group in
966  the source RPM (which is the owner/group of the files as staying on
967  the package author system) is not existing on the target system, of
968  course. */
969  if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
970  if (!fi->isSource) {
971  if (iosm->goal == IOSM_PKGINSTALL)
973  _("user %s does not exist - using root\n"), fi->fuser[i]);
974  uid = 0;
975  finalMode &= ~S_ISUID; /* turn off suid bit */
976  }
977  }
978 
979  if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
980  if (!fi->isSource) {
981  if (iosm->goal == IOSM_PKGINSTALL)
983  _("group %s does not exist - using root\n"), fi->fgroup[i]);
984  gid = 0;
985  finalMode &= ~S_ISGID; /* turn off sgid bit */
986  }
987  }
988 
989  if (iosm->mapFlags & IOSM_MAP_MODE)
990  st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
991  if (iosm->mapFlags & IOSM_MAP_TYPE) {
992  st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
993  if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
994  && st->st_nlink == 0)
995  st->st_nlink = 1;
996  st->st_rdev = finalRdev;
997  st->st_mtime = finalMtime;
998  }
999  if (iosm->mapFlags & IOSM_MAP_UID)
1000  st->st_uid = uid;
1001  if (iosm->mapFlags & IOSM_MAP_GID)
1002  st->st_gid = gid;
1003 
1004  /*
1005  * Set file digest (if not disabled).
1006  */
1007  if (!iosm->nofdigests) {
1008  iosm->fdigestalgo = fi->digestalgo;
1009  iosm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL);
1010  iosm->digestlen = fi->digestlen;
1011  iosm->digest = (fi->digests ? (fi->digests + (iosm->digestlen * i)) : NULL);
1012  } else {
1013  iosm->fdigestalgo = 0;
1014  iosm->fdigest = NULL;
1015  iosm->digestlen = 0;
1016  iosm->digest = NULL;
1017  }
1018  }
1019  return 0;
1020 }
1021 
1027 /*@-compdef@*/
1028 static int extractRegular(/*@special@*/ IOSM_t iosm)
1029  /*@uses iosm->fdigest, iosm->digest, iosm->sb, iosm->wfd @*/
1030  /*@globals h_errno, fileSystem, internalState @*/
1031  /*@modifies iosm, fileSystem, internalState @*/
1032 {
1033  const struct stat * st = &iosm->sb;
1034  size_t left = (size_t) st->st_size;
1035  int rc = 0;
1036  int xx;
1037 
1038  rc = iosmNext(iosm, IOSM_WOPEN);
1039  if (rc)
1040  goto exit;
1041 
1042  if (st->st_size > 0 && (iosm->fdigest != NULL || iosm->digest != NULL))
1043  fdInitDigest(iosm->wfd, (pgpHashAlgo)iosm->fdigestalgo, 0);
1044 
1045  while (left) {
1046 
1047  iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left);
1048  rc = iosmNext(iosm, IOSM_DREAD);
1049  if (rc)
1050  goto exit;
1051 
1052  rc = iosmNext(iosm, IOSM_WRITE);
1053  if (rc)
1054  goto exit;
1055 
1056  left -= iosm->wrnb;
1057 
1058  /* Notify iff progress, completion is done elsewhere */
1059  if (!rc && left)
1060  (void) iosmNext(iosm, IOSM_NOTIFY);
1061  }
1062 
1063  xx = fsync(Fileno(iosm->wfd));
1064 
1065  if (st->st_size > 0 && (iosm->fdigest || iosm->digest)) {
1066  void * digest = NULL;
1067  int asAscii = (iosm->digest == NULL ? 1 : 0);
1068 
1069  (void) Fflush(iosm->wfd);
1070  fdFiniDigest(iosm->wfd, (pgpHashAlgo)iosm->fdigestalgo, &digest, NULL, asAscii);
1071 
1072  if (digest == NULL) {
1074  goto exit;
1075  }
1076 
1077  if (iosm->digest != NULL) {
1078  if (memcmp(digest, iosm->digest, iosm->digestlen))
1080  } else {
1081  if (strcmp((char *)digest, iosm->fdigest))
1083  }
1084  digest = _free(digest);
1085  }
1086 
1087 exit:
1088  (void) iosmNext(iosm, IOSM_WCLOSE);
1089  return rc;
1090 }
1091 /*@=compdef@*/
1092 
1099 /*@-compdef -compmempass@*/
1100 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t iosm, int writeData)
1101  /*@uses iosm->path, iosm->opath, iosm->sb, iosm->osb, iosm->cfd @*/
1102  /*@globals h_errno, fileSystem, internalState @*/
1103  /*@modifies iosm, fileSystem, internalState @*/
1104 {
1105  const char * path = iosm->path;
1106  const char * opath = iosm->opath;
1107  struct stat * st = &iosm->sb;
1108  struct stat * ost = &iosm->osb;
1109  size_t left;
1110  int xx;
1111  int rc;
1112 
1113  st->st_size = (writeData ? ost->st_size : 0);
1114 
1115  if (S_ISDIR(st->st_mode)) {
1116  st->st_size = 0;
1117  } else if (S_ISLNK(st->st_mode)) {
1118  /*
1119  * While linux puts the size of a symlink in the st_size field,
1120  * I don't think that's a specified standard.
1121  */
1122  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
1123  rc = iosmUNSAFE(iosm, IOSM_READLINK);
1124  if (rc) goto exit;
1125  st->st_size = iosm->rdnb;
1126  iosm->lpath = xstrdup(iosm->rdbuf); /* XXX save readlink return. */
1127  }
1128 
1129  if (iosm->mapFlags & IOSM_MAP_ABSOLUTE) {
1130  size_t nb=strlen(iosm->dirName) + strlen(iosm->baseName) + sizeof(".");
1131  char * t = (char *) alloca(nb);
1132  *t = '\0';
1133  iosm->path = t;
1134  if (iosm->mapFlags & IOSM_MAP_ADDDOT)
1135  *t++ = '.';
1136  t = stpcpy( stpcpy(t, iosm->dirName), iosm->baseName);
1137  } else if (iosm->mapFlags & IOSM_MAP_PATH) {
1138  rpmfi fi = (rpmfi) iosmGetFi(iosm);
1139  if (fi->apath) {
1140  const char * apath = NULL;
1141  (void) urlPath(fi->apath[iosm->ix], &apath);
1142  iosm->path = apath + fi->striplen;
1143  } else
1144  iosm->path = fi->bnl[iosm->ix];
1145  }
1146 
1147  rc = iosmNext(iosm, IOSM_HWRITE);
1148  iosm->path = path;
1149  if (rc) goto exit;
1150 
1151  if (writeData && S_ISREG(st->st_mode)) {
1152 #if defined(HAVE_MMAP)
1153  char * rdbuf = NULL;
1154  void * mapped = (void *)-1;
1155  size_t nmapped = 0;
1156  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */
1157  int use_mmap = (st->st_size <= 0x07ffffff);
1158 #endif
1159 
1160  rc = iosmNext(iosm, IOSM_ROPEN);
1161  if (rc) goto exit;
1162 
1163  /* XXX unbuffered mmap generates *lots* of fdio debugging */
1164 #if defined(HAVE_MMAP)
1165  if (use_mmap) {
1166  mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(iosm->rfd), 0);
1167  if (mapped != (void *)-1) {
1168  rdbuf = iosm->rdbuf;
1169  iosm->rdbuf = (char *) mapped;
1170  iosm->rdlen = nmapped = st->st_size;
1171 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1172  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1173 #endif
1174  }
1175  }
1176 #endif
1177 
1178  left = st->st_size;
1179 
1180  while (left) {
1181 #if defined(HAVE_MMAP)
1182  if (mapped != (void *)-1) {
1183  iosm->rdnb = nmapped;
1184  } else
1185 #endif
1186  {
1187  iosm->rdlen = (left > iosm->rdsize ? iosm->rdsize : left),
1188  rc = iosmNext(iosm, IOSM_READ);
1189  if (rc) goto exit;
1190  }
1191 
1192  /* XXX DWRITE uses rdnb for I/O length. */
1193  rc = iosmNext(iosm, IOSM_DWRITE);
1194  if (rc) goto exit;
1195 
1196  left -= iosm->wrnb;
1197  }
1198 
1199 #if defined(HAVE_MMAP)
1200  if (mapped != (void *)-1) {
1201 /* XXX splint misses size_t 2nd arg. */
1202 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC);
1203 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1204  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1205 #endif
1206  xx = munmap(mapped, nmapped);
1207  iosm->rdbuf = rdbuf;
1208  } else
1209 #endif
1210  { int fdno = Fileno(iosm->rfd);
1211  if (fdno >= 0)
1212  xx = fsync(fdno); /* XXX coverity #1035827 */
1213  }
1214 
1215  }
1216 
1217  rc = iosmNext(iosm, IOSM_PAD);
1218  if (rc) goto exit;
1219 
1220  rc = 0;
1221 
1222 exit:
1223  if (iosm->rfd != NULL)
1224  (void) iosmNext(iosm, IOSM_RCLOSE);
1225 /*@-dependenttrans@*/
1226  iosm->opath = opath;
1227  iosm->path = path;
1228 /*@=dependenttrans@*/
1229  return rc;
1230 }
1231 /*@=compdef =compmempass@*/
1232 
1238 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1239  /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->li, iosm->failedFile @*/
1240  /*@globals h_errno, fileSystem, internalState @*/
1241  /*@modifies iosm, fileSystem, internalState @*/
1242 {
1243  const char * path = iosm->path;
1244  const char * lpath = iosm->lpath;
1245  const char * nsuffix = iosm->nsuffix;
1246  int iterIndex = iosm->ix;
1247  int ec = 0;
1248  int rc;
1249  int i;
1250  const char * linkpath = NULL;
1251  int firstfile = 1;
1252 
1253  iosm->path = NULL;
1254  iosm->lpath = NULL;
1255  iosm->nsuffix = NULL;
1256  iosm->ix = -1;
1257 
1258  for (i = iosm->li->nlink - 1; i >= 0; i--) {
1259 
1260  if (iosm->li->filex[i] < 0) continue;
1261 
1262  iosm->ix = iosm->li->filex[i];
1263 /*@-compdef@*/
1264  rc = iosmNext(iosm, IOSM_MAP);
1265 /*@=compdef@*/
1266 
1267  /* XXX tar and cpio have to do things differently. */
1268  if (iosm->headerWrite == tarHeaderWrite) {
1269  if (firstfile) {
1270  const char * apath = NULL;
1271  char *t;
1272  (void) urlPath(iosm->path, &apath);
1273  /* Remove the buildroot prefix. */
1274  t = (char *) xmalloc(sizeof(".") + strlen(apath + iosm->astriplen));
1275  (void) stpcpy( stpcpy(t, "."), apath + iosm->astriplen);
1276  linkpath = t;
1277  firstfile = 0;
1278  } else
1279  iosm->lpath = linkpath;
1280 
1281  /* Write data after first link for tar. */
1282  rc = writeFile(iosm, (iosm->lpath == NULL));
1283  } else {
1284  /* Write data after last link for cpio. */
1285  rc = writeFile(iosm, (i == 0));
1286  }
1287  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1288  ec = rc;
1289  *iosm->failedFile = xstrdup(iosm->path);
1290  }
1291 
1292  iosm->path = _free(iosm->path);
1293  iosm->li->filex[i] = -1;
1294  }
1295 
1296 /*@-dependenttrans@*/
1297  linkpath = _free(linkpath);
1298 /*@=dependenttrans@*/
1299  iosm->ix = iterIndex;
1300  iosm->nsuffix = nsuffix;
1301  iosm->lpath = lpath;
1302  iosm->path = path;
1303  return ec;
1304 }
1305 
1311 /*@-compdef@*/
1312 static int iosmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1313  /*@uses iosm->path, iosm->opath, iosm->nsuffix, iosm->ix, iosm->li @*/
1314  /*@globals h_errno, fileSystem, internalState @*/
1315  /*@modifies iosm, fileSystem, internalState @*/
1316 {
1317  const char * path = iosm->path;
1318  const char * opath = iosm->opath;
1319  const char * nsuffix = iosm->nsuffix;
1320  int iterIndex = iosm->ix;
1321  int ec = 0;
1322  int rc;
1323  int i;
1324 
1325  iosm->path = NULL;
1326  iosm->opath = NULL;
1327  iosm->nsuffix = NULL;
1328  iosm->ix = -1;
1329 
1330  iosm->ix = iosm->li->filex[iosm->li->createdPath];
1331  rc = iosmNext(iosm, IOSM_MAP);
1332  iosm->opath = iosm->path;
1333  iosm->path = NULL;
1334  for (i = 0; i < iosm->li->nlink; i++) {
1335  if (iosm->li->filex[i] < 0) continue;
1336  if (iosm->li->createdPath == i) continue;
1337 
1338  iosm->ix = iosm->li->filex[i];
1339  iosm->path = _free(iosm->path);
1340  rc = iosmNext(iosm, IOSM_MAP);
1341  if (iosmFileActionSkipped(iosm->action)) continue;
1342 
1343  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
1344  if (!rc) continue;
1345  if (!(rc == IOSMERR_ENOENT)) break;
1346 
1347  /* XXX link(iosm->opath, iosm->path) */
1348  rc = iosmNext(iosm, IOSM_LINK);
1349  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1350  ec = rc;
1351  *iosm->failedFile = xstrdup(iosm->path);
1352  }
1353 
1354  iosm->li->linksLeft--;
1355  }
1356  iosm->path = _free(iosm->path);
1357  iosm->opath = _free(iosm->opath);
1358 
1359  iosm->ix = iterIndex;
1360  iosm->nsuffix = nsuffix;
1361  iosm->path = path;
1362  iosm->opath = opath;
1363  return ec;
1364 }
1365 /*@=compdef@*/
1366 
1372 /*@-compdef@*/
1373 static int iosmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1374  /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->sb,
1375  iosm->li, iosm->links @*/
1376  /*@globals h_errno, fileSystem, internalState @*/
1377  /*@modifies iosm, fileSystem, internalState @*/
1378 {
1379  const char * path = iosm->path;
1380  const char * nsuffix = iosm->nsuffix;
1381  int iterIndex = iosm->ix;
1382  struct stat * st = &iosm->sb;
1383  int rc = 0;
1384  int i;
1385 
1386  iosm->path = NULL;
1387  iosm->nsuffix = NULL;
1388  iosm->ix = -1;
1389 
1390  for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li->next) {
1391  if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == st->st_dev)
1392  break;
1393  }
1394 
1395 assert(iosm->li); /* XXX coverity #1035793 */
1396  for (i = 0; i < iosm->li->nlink; i++) {
1397  if (iosm->li->filex[i] < 0) continue;
1398  iosm->ix = iosm->li->filex[i];
1399  rc = iosmNext(iosm, IOSM_MAP);
1400  if (!iosmFileActionSkipped(iosm->action))
1401  rc = iosmNext(iosm, IOSM_COMMIT);
1402  iosm->path = _free(iosm->path);
1403  iosm->li->filex[i] = -1;
1404  }
1405 
1406  iosm->ix = iterIndex;
1407  iosm->nsuffix = nsuffix;
1408  iosm->path = path;
1409  return rc;
1410 }
1411 /*@=compdef@*/
1412 
1418 static int iosmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1419  /*@uses iosm->path, iosm->dnlx, iosm->ldn, iosm->rdbuf, iosm->iter @*/
1420  /*@globals h_errno, fileSystem, internalState @*/
1421  /*@modifies iosm, fileSystem, internalState @*/
1422 {
1423  const char * path = iosm->path;
1424  void * dnli = dnlInitIterator(iosm, 1);
1425  char * dn = iosm->rdbuf;
1426  int dc = dnlCount((DNLI_t)dnli);
1427  int rc = 0;
1428 
1429  iosm->path = NULL;
1430  dn[0] = '\0';
1431  /*@-observertrans -dependenttrans@*/
1432  if (iosm->ldn != NULL && iosm->dnlx != NULL)
1433  while ((iosm->path = dnlNextIterator((DNLI_t)dnli)) != NULL) {
1434  size_t dnlen = strlen(iosm->path);
1435  char * te;
1436 
1437  dc = dnlIndex((DNLI_t)dnli);
1438  if (iosm->dnlx[dc] < 1 || (size_t)iosm->dnlx[dc] >= dnlen)
1439  continue;
1440 
1441  /* Copy to avoid const on iosm->path. */
1442  te = stpcpy(dn, iosm->path) - 1;
1443  iosm->path = dn;
1444 
1445  /* Remove generated directories. */
1446  /*@-usereleased@*/ /* LCL: te used after release? */
1447  do {
1448  if (*te == '/') {
1449  *te = '\0';
1450 /*@-compdef@*/
1451  rc = iosmNext(iosm, IOSM_RMDIR);
1452 /*@=compdef@*/
1453  *te = '/';
1454  }
1455  if (rc)
1456  /*@innerbreak@*/ break;
1457  te--;
1458  } while ((te - iosm->path) > iosm->dnlx[dc]);
1459  /*@=usereleased@*/
1460  }
1461  dnli = dnlFreeIterator(dnli);
1462  /*@=observertrans =dependenttrans@*/
1463 
1464  iosm->path = path;
1465  return rc;
1466 }
1467 
1473 static int iosmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1474  /*@uses iosm->path, iosm->sb, iosm->osb, iosm->rdbuf, iosm->iter,
1475  iosm->ldn, iosm->ldnlen, iosm->ldnalloc @*/
1476  /*@defines iosm->dnlx, iosm->ldn @*/
1477  /*@globals h_errno, fileSystem, internalState @*/
1478  /*@modifies iosm, fileSystem, internalState @*/
1479 {
1480  struct stat * st = &iosm->sb;
1481  struct stat * ost = &iosm->osb;
1482  const char * path = iosm->path;
1483  mode_t st_mode = st->st_mode;
1484  void * dnli = dnlInitIterator(iosm, 0);
1485  char * dn = iosm->rdbuf;
1486  int dc = dnlCount((DNLI_t)dnli);
1487  int rc = 0;
1488  size_t i;
1489 
1490  iosm->path = NULL;
1491 
1492  dn[0] = '\0';
1493  iosm->dnlx = (unsigned short *) (dc ? xcalloc(dc, sizeof(*iosm->dnlx)) : NULL);
1494  /*@-observertrans -dependenttrans@*/
1495  if (iosm->dnlx != NULL)
1496  while ((iosm->path = dnlNextIterator((DNLI_t)dnli)) != NULL) {
1497  size_t dnlen = strlen(iosm->path);
1498  char * te;
1499 
1500  dc = dnlIndex((DNLI_t)dnli);
1501  if (dc < 0) continue;
1502  iosm->dnlx[dc] = (unsigned short) dnlen;
1503  if (dnlen <= 1)
1504  continue;
1505 
1506  /*@-compdef -nullpass@*/ /* FIX: iosm->ldn not defined ??? */
1507  if (dnlen <= iosm->ldnlen && !strcmp(iosm->path, iosm->ldn))
1508  continue;
1509  /*@=compdef =nullpass@*/
1510 
1511  /* Copy to avoid const on iosm->path. */
1512  (void) stpcpy(dn, iosm->path);
1513  iosm->path = dn;
1514 
1515  /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
1516  (void) urlPath(dn, (const char **)&te);
1517  for (i = 1, te++; *te != '\0'; te++, i++) {
1518  if (*te != '/')
1519  /*@innercontinue@*/ continue;
1520 
1521  *te = '\0';
1522 
1523  /* Already validated? */
1524  /*@-usedef -compdef -nullpass -nullderef@*/
1525  if (i < iosm->ldnlen &&
1526  (iosm->ldn[i] == '/' || iosm->ldn[i] == '\0') &&
1527  !strncmp(iosm->path, iosm->ldn, i))
1528  {
1529  *te = '/';
1530  /* Move pre-existing path marker forward. */
1531  iosm->dnlx[dc] = (te - dn);
1532  /*@innercontinue@*/ continue;
1533  }
1534  /*@=usedef =compdef =nullpass =nullderef@*/
1535 
1536  /* Validate next component of path. */
1537  rc = iosmUNSAFE(iosm, IOSM_LSTAT);
1538  *te = '/';
1539 
1540  /* Directory already exists? */
1541  if (rc == 0 && S_ISDIR(ost->st_mode)) {
1542  /* Move pre-existing path marker forward. */
1543  iosm->dnlx[dc] = (te - dn);
1544  } else if (rc == IOSMERR_ENOENT) {
1545  rpmfi fi = (rpmfi) iosmGetFi(iosm);
1546  *te = '\0';
1547  st->st_mode = S_IFDIR | (fi->dperms & 07777);
1548  rc = iosmNext(iosm, IOSM_MKDIR);
1549  if (!rc) {
1550 #if defined(_USE_RPMSX)
1551  /* XXX FIXME? only new dir will have context set. */
1552  /* Get file security context from patterns. */
1553  if (!fsm->nofcontexts) {
1554  iosm->fcontext =
1555  rpmsxMatch(NULL, iosm->path, st->st_mode);
1556  if (iosm->fcontext != NULL)
1557  rc = iosmNext(iosm, IOSM_LSETFCON);
1558  } else
1559 #endif
1560  iosm->fcontext = NULL;
1562  D_("%s directory created with perms %04o, context %s.\n"),
1563  iosm->path, (unsigned)(st->st_mode & 07777),
1564  (iosm->fcontext ? iosm->fcontext : "(no context)"));
1565 #if defined(_USE_RPMSX)
1566  iosm->fcontext = _free(iosm->fcontext);
1567 #endif
1568  }
1569  *te = '/';
1570  }
1571  if (rc)
1572  /*@innerbreak@*/ break;
1573  }
1574  if (rc) break;
1575 
1576  /* Save last validated path. */
1577 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1578  if (iosm->ldnalloc < (dnlen + 1)) {
1579  iosm->ldnalloc = dnlen + 100;
1580  iosm->ldn = (char *) xrealloc(iosm->ldn, iosm->ldnalloc);
1581  }
1582  if (iosm->ldn != NULL) { /* XXX can't happen */
1583  strcpy(iosm->ldn, iosm->path);
1584  iosm->ldnlen = dnlen;
1585  }
1586 /*@=compdef@*/
1587  }
1588  dnli = dnlFreeIterator(dnli);
1589  /*@=observertrans =dependenttrans@*/
1590 
1591  iosm->path = path;
1592  st->st_mode = st_mode; /* XXX restore st->st_mode */
1593 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1594  return rc;
1595 /*@=compdef@*/
1596 }
1597 
1598 #ifdef NOTYET
1599 
1604 static int iosmStat(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1605  /*@globals fileSystem, internalState @*/
1606  /*@modifies iosm, fileSystem, internalState @*/
1607 {
1608  int rc = 0;
1609 
1610  if (iosm->path != NULL) {
1611  int saveernno = errno;
1612  rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1613  ? IOSM_LSTAT : IOSM_STAT));
1614  if (rc == IOSMERR_ENOENT) {
1615  errno = saveerrno;
1616  rc = 0;
1617  iosm->exists = 0;
1618  } else if (rc == 0) {
1619  iosm->exists = 1;
1620  }
1621  } else {
1622  /* Skip %ghost files on build. */
1623  iosm->exists = 0;
1624  }
1625  return rc;
1626 }
1627 #endif
1628 
1629 #define IS_DEV_LOG(_x) \
1630  ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
1631  !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
1632  ((_x)[sizeof("/dev/log")-1] == '\0' || \
1633  (_x)[sizeof("/dev/log")-1] == ';'))
1634 
1635 /*@-compmempass@*/
1637 {
1638 #ifdef NOTUSED
1639  iosmFileStage prevStage = iosm->stage;
1640  const char * const prev = iosmFileStageString(prevStage);
1641 #endif
1642  const char * const cur = iosmFileStageString(stage);
1643  struct stat * st = &iosm->sb;
1644  struct stat * ost = &iosm->osb;
1645  int saveerrno = errno;
1646  int rc = iosm->rc;
1647  size_t left;
1648  int i;
1649 
1650 #define _fafilter(_a) \
1651  (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
1652  ? iosmFileActionString(_a) : "")
1653 
1654  if (stage & IOSM_DEAD) {
1655  /* do nothing */
1656  } else if (stage & IOSM_INTERNAL) {
1657  if (iosm->debug && !(stage & IOSM_SYSCALL))
1658  rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1659  cur,
1660  (unsigned)st->st_mode, (int)st->st_nlink,
1661  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1662  (iosm->path ? iosm->path : ""),
1663  _fafilter(iosm->action));
1664  } else {
1665  const char * apath = NULL;
1666  if (iosm->path)
1667  (void) urlPath(iosm->path, &apath);
1668  iosm->stage = stage;
1669  if (iosm->debug || !(stage & IOSM_VERBOSE))
1670  rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1671  cur,
1672  (unsigned)st->st_mode, (int)st->st_nlink,
1673  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1674  (apath ? apath + iosm->astriplen : ""),
1675  _fafilter(iosm->action));
1676  }
1677 #undef _fafilter
1678 
1679  switch (stage) {
1680  case IOSM_UNKNOWN:
1681  break;
1682  case IOSM_PKGINSTALL:
1683  while (1) {
1684  /* Clean iosm, free'ing memory. Read next archive header. */
1685  rc = iosmUNSAFE(iosm, IOSM_INIT);
1686 
1687  /* Exit on end-of-payload. */
1688  if (rc == IOSMERR_HDR_TRAILER) {
1689  rc = 0;
1690  /*@loopbreak@*/ break;
1691  }
1692 
1693  /* Exit on error. */
1694  if (rc) {
1695  iosm->postpone = 1;
1696  (void) iosmNext(iosm, IOSM_UNDO);
1697  /*@loopbreak@*/ break;
1698  }
1699 
1700  /* Extract file from archive. */
1701  rc = iosmNext(iosm, IOSM_PROCESS);
1702  if (rc) {
1703  (void) iosmNext(iosm, IOSM_UNDO);
1704  /*@loopbreak@*/ break;
1705  }
1706 
1707  /* Notify on success. */
1708  (void) iosmNext(iosm, IOSM_NOTIFY);
1709 
1710  rc = iosmNext(iosm, IOSM_FINI);
1711  if (rc) {
1712  /*@loopbreak@*/ break;
1713  }
1714  }
1715  break;
1716  case IOSM_PKGERASE:
1717  case IOSM_PKGCOMMIT:
1718  while (1) {
1719  /* Clean iosm, free'ing memory. */
1720  rc = iosmUNSAFE(iosm, IOSM_INIT);
1721 
1722  /* Exit on end-of-payload. */
1723  if (rc == IOSMERR_HDR_TRAILER) {
1724  rc = 0;
1725  /*@loopbreak@*/ break;
1726  }
1727 
1728  /* Rename/erase next item. */
1729  if (iosmNext(iosm, IOSM_FINI))
1730  /*@loopbreak@*/ break;
1731  }
1732  break;
1733  case IOSM_PKGBUILD:
1734  while (1) {
1735 
1736  rc = iosmUNSAFE(iosm, IOSM_INIT);
1737 
1738  /* Exit on end-of-payload. */
1739  if (rc == IOSMERR_HDR_TRAILER) {
1740  rc = 0;
1741  /*@loopbreak@*/ break;
1742  }
1743 
1744  /* Exit on error. */
1745  if (rc) {
1746  iosm->postpone = 1;
1747  (void) iosmNext(iosm, IOSM_UNDO);
1748  /*@loopbreak@*/ break;
1749  }
1750 
1751  /* Copy file into archive. */
1752  rc = iosmNext(iosm, IOSM_PROCESS);
1753  if (rc) {
1754  (void) iosmNext(iosm, IOSM_UNDO);
1755  /*@loopbreak@*/ break;
1756  }
1757 
1758  /* Notify on success. */
1759  (void) iosmNext(iosm, IOSM_NOTIFY);
1760 
1761  if (iosmNext(iosm, IOSM_FINI))
1762  /*@loopbreak@*/ break;
1763  }
1764 
1765  /* Flush partial sets of hard linked files. */
1766  if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) {
1767  int nlink, j;
1768  while ((iosm->li = iosm->links) != NULL) {
1769  iosm->links = iosm->li->next;
1770  iosm->li->next = NULL;
1771 
1772  /* Re-calculate link count for archive header. */
1773  for (j = -1, nlink = 0, i = 0; i < iosm->li->nlink; i++) {
1774  if (iosm->li->filex[i] < 0)
1775  /*@innercontinue@*/ continue;
1776  nlink++;
1777  if (j == -1) j = i;
1778  }
1779  /* XXX force the contents out as well. */
1780  if (j != 0) {
1781  iosm->li->filex[0] = iosm->li->filex[j];
1782  iosm->li->filex[j] = -1;
1783  }
1784  iosm->li->sb.st_nlink = nlink;
1785 
1786  iosm->sb = iosm->li->sb; /* structure assignment */
1787  iosm->osb = iosm->sb; /* structure assignment */
1788 
1789  if (!rc) rc = writeLinkedFile(iosm);
1790 
1791  iosm->li = (struct hardLink_s *) freeHardLink((struct hardLink_s *) iosm->li);
1792  }
1793  }
1794 
1795  if (!rc)
1796  rc = iosmNext(iosm, IOSM_TRAILER);
1797 
1798  break;
1799  case IOSM_CREATE:
1800  iosm->path = _free(iosm->path);
1801  iosm->lpath = _free(iosm->lpath);
1802  iosm->opath = _free(iosm->opath);
1803  iosm->dnlx = _free(iosm->dnlx);
1804 
1805  iosm->ldn = _free(iosm->ldn);
1806  iosm->ldnalloc = iosm->ldnlen = 0;
1807 
1808  iosm->rdsize = iosm->wrsize = 0;
1809  iosm->rdbuf = iosm->rdb = _free(iosm->rdb);
1810  iosm->wrbuf = iosm->wrb = _free(iosm->wrb);
1811  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
1812  iosm->rdsize = 16 * BUFSIZ;
1813  iosm->rdbuf = iosm->rdb = (char *) xmalloc(iosm->rdsize);
1814  iosm->wrsize = 16 * BUFSIZ;
1815  iosm->wrbuf = iosm->wrb = (char *) xmalloc(iosm->wrsize);
1816  }
1817 
1818  iosm->mkdirsdone = 0;
1819  iosm->ix = -1;
1820  iosm->links = NULL;
1821  iosm->li = NULL;
1822  errno = 0; /* XXX get rid of EBADF */
1823 
1824  /* Detect and create directories not explicitly in package. */
1825  if (iosm->goal == IOSM_PKGINSTALL) {
1826 /*@-compdef@*/
1827  rc = iosmNext(iosm, IOSM_MKDIRS);
1828 /*@=compdef@*/
1829  if (!rc) iosm->mkdirsdone = 1;
1830  }
1831 
1832  break;
1833  case IOSM_INIT:
1834  iosm->path = _free(iosm->path);
1835  iosm->lpath = _free(iosm->lpath);
1836  iosm->postpone = 0;
1837  iosm->diskchecked = iosm->exists = 0;
1838  iosm->subdir = NULL;
1839  iosm->suffix = (iosm->sufbuf[0] != '\0' ? iosm->sufbuf : NULL);
1840  iosm->action = FA_UNKNOWN;
1841  iosm->osuffix = NULL;
1842  iosm->nsuffix = NULL;
1843 
1844  if (iosm->goal == IOSM_PKGINSTALL) {
1845  /* Read next header from payload, checking for end-of-payload. */
1846  rc = iosmUNSAFE(iosm, IOSM_NEXT);
1847  }
1848  if (rc) break;
1849 
1850  /* Identify mapping index. */
1851  iosm->ix = ((iosm->goal == IOSM_PKGINSTALL)
1852  ? mapFind(iosm->iter, iosm->path) : mapNextIterator(iosm->iter));
1853 
1854  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
1855  if (fi != NULL && !(fi->mapflags & IOSM_PAYLOAD_LIST)) {
1856  /* Detect end-of-loop and/or mapping error. */
1857  if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) {
1858  if (iosm->ix < 0) {
1859  if (iosm->goal == IOSM_PKGINSTALL) {
1860 #if 0
1862  _("archive file %s was not found in header\n"),
1863  iosm->path);
1864 #endif
1865  if (iosm->failedFile && *iosm->failedFile == NULL)
1866  *iosm->failedFile = xstrdup(iosm->path);
1867  rc = IOSMERR_UNMAPPED_FILE;
1868  } else
1869  rc = IOSMERR_HDR_TRAILER;
1870  break;
1871  }
1872  }
1873 
1874  /* On non-install, mode must be known so dirs don't get suffixed. */
1875  if (iosm->goal != IOSM_PKGINSTALL)
1876  st->st_mode = fi->fmodes[iosm->ix];
1877  }
1878  }
1879 
1880  /* Generate file path. */
1881  rc = iosmNext(iosm, IOSM_MAP);
1882  if (rc) break;
1883 
1884  /* Perform lstat/stat for disk file. */
1885 #ifdef NOTYET
1886  rc = iosmStat(iosm);
1887 #else
1888  if (iosm->path != NULL &&
1889  !(iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))
1890  {
1891  rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1892  ? IOSM_LSTAT : IOSM_STAT));
1893  if (rc == IOSMERR_ENOENT) {
1894  errno = saveerrno;
1895  rc = 0;
1896  iosm->exists = 0;
1897  } else if (rc == 0) {
1898  iosm->exists = 1;
1899  }
1900  } else {
1901  /* Skip %ghost files on build. */
1902  iosm->exists = 0;
1903  }
1904 #endif
1905  iosm->diskchecked = 1;
1906  if (rc) break;
1907 
1908  /* On non-install, the disk file stat is what's remapped. */
1909  if (iosm->goal != IOSM_PKGINSTALL)
1910  *st = *ost; /* structure assignment */
1911 
1912  /* Remap file perms, owner, and group. */
1913  rc = iosmMapAttrs(iosm);
1914  if (rc) break;
1915 
1916  iosm->postpone = iosmFileActionSkipped(iosm->action);
1917  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
1918  /*@-evalorder@*/ /* FIX: saveHardLink can modify iosm */
1919  if (S_ISREG(st->st_mode) && st->st_nlink > 1)
1920  iosm->postpone = saveHardLink(iosm);
1921  /*@=evalorder@*/
1922  }
1923  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
1924  if (fi != NULL && (fi->mapflags & IOSM_PAYLOAD_LIST))
1925  iosm->postpone = 1;
1926  }
1927  break;
1928  case IOSM_PRE:
1929  break;
1930  case IOSM_MAP:
1931  rc = iosmMapPath(iosm);
1932  break;
1933  case IOSM_MKDIRS:
1934  rc = iosmMkdirs(iosm);
1935  break;
1936  case IOSM_RMDIRS:
1937  if (iosm->dnlx)
1938  rc = iosmRmdirs(iosm);
1939  break;
1940  case IOSM_PROCESS:
1941  if (iosm->postpone) {
1942  if (iosm->goal == IOSM_PKGINSTALL) {
1943  /* XXX Skip over file body, archive headers already done. */
1944  if (S_ISREG(st->st_mode))
1945  rc = iosmNext(iosm, IOSM_EAT);
1946  }
1947  break;
1948  }
1949 
1950  if (iosm->goal == IOSM_PKGBUILD) {
1951  if (iosm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
1952  break;
1953  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1954  struct hardLink_s * li, * prev;
1955 
1956 if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) break;
1957  rc = writeLinkedFile(iosm);
1958  if (rc) break; /* W2DO? */
1959 
1960  for (li = iosm->links, prev = NULL; li; prev = li, li = li->next)
1961  if (li == iosm->li)
1962  /*@loopbreak@*/ break;
1963 
1964  if (prev == NULL)
1965  iosm->links = iosm->li->next;
1966  else
1967  prev->next = iosm->li->next;
1968  iosm->li->next = NULL;
1969  iosm->li = (struct hardLink_s *) freeHardLink((struct hardLink_s *) iosm->li);
1970  } else {
1971  rc = writeFile(iosm, 1);
1972  }
1973  break;
1974  }
1975 
1976  if (iosm->goal != IOSM_PKGINSTALL)
1977  break;
1978 
1979  if (S_ISREG(st->st_mode) && iosm->lpath != NULL) {
1980  const char * opath = iosm->opath;
1981  char * t = (char *) xmalloc(strlen(iosm->lpath+1) + strlen(iosm->suffix) + 1);
1982  (void) stpcpy(t, iosm->lpath+1);
1983  iosm->opath = t;
1984  /* XXX link(iosm->opath, iosm->path) */
1985  rc = iosmNext(iosm, IOSM_LINK);
1986  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1987  *iosm->failedFile = xstrdup(iosm->path);
1988  }
1989  iosm->opath = _free(iosm->opath);
1990  iosm->opath = opath;
1991  break; /* XXX so that delayed hard links get skipped. */
1992  }
1993  if (S_ISREG(st->st_mode)) {
1994  const char * path = iosm->path;
1995  if (iosm->osuffix)
1996  iosm->path = iosmFsPath(iosm, st, NULL, NULL);
1997  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
1998 
1999  if (rc == 0 && iosm->osuffix) {
2000  const char * opath = iosm->opath;
2001  iosm->opath = iosm->path;
2002  iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix);
2003  rc = iosmNext(iosm, IOSM_RENAME);
2004  if (!rc)
2006  _("%s saved as %s\n"),
2007  (iosm->opath ? iosm->opath : ""),
2008  (iosm->path ? iosm->path : ""));
2009  iosm->path = _free(iosm->path);
2010  iosm->opath = opath;
2011  }
2012 
2013  /*@-dependenttrans@*/
2014  iosm->path = path;
2015  /*@=dependenttrans@*/
2016  if (!(rc == IOSMERR_ENOENT)) return rc;
2017  rc = extractRegular(iosm);
2018  } else if (S_ISDIR(st->st_mode)) {
2019  mode_t st_mode = st->st_mode;
2020  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2021  if (rc == IOSMERR_ENOENT) {
2022  st->st_mode &= ~07777; /* XXX abuse st->st_mode */
2023  st->st_mode |= 00700;
2024  rc = iosmNext(iosm, IOSM_MKDIR);
2025  st->st_mode = st_mode; /* XXX restore st->st_mode */
2026  }
2027  } else if (S_ISLNK(st->st_mode)) {
2028 assert(iosm->lpath != NULL);
2029  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2030  if (rc == IOSMERR_ENOENT)
2031  rc = iosmNext(iosm, IOSM_SYMLINK);
2032  } else if (S_ISFIFO(st->st_mode)) {
2033  mode_t st_mode = st->st_mode;
2034  /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
2035  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2036  if (rc == IOSMERR_ENOENT) {
2037  st->st_mode = 0000; /* XXX abuse st->st_mode */
2038  rc = iosmNext(iosm, IOSM_MKFIFO);
2039  st->st_mode = st_mode; /* XXX restore st->st_mode */
2040  }
2041  } else if (S_ISCHR(st->st_mode) ||
2042  S_ISBLK(st->st_mode) ||
2043  /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
2044  {
2045  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2046  if (rc == IOSMERR_ENOENT)
2047  rc = iosmNext(iosm, IOSM_MKNOD);
2048  } else {
2049  /* XXX Repackaged payloads may be missing files. */
2050  if (iosm->repackaged)
2051  break;
2052 
2053  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2054  if (!IS_DEV_LOG(iosm->path))
2056  }
2057  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
2058  iosm->li->createdPath = iosm->li->linkIndex;
2059  rc = iosmMakeLinks(iosm);
2060  }
2061  break;
2062  case IOSM_POST:
2063  break;
2064  case IOSM_MKLINKS:
2065  rc = iosmMakeLinks(iosm);
2066  break;
2067  case IOSM_NOTIFY: /* XXX move from iosm to psm -> tsm */
2068 #if defined(_USE_RPMTS)
2069  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
2070  rpmfi fi = iosmGetFi(iosm);
2071  rpmuint64_t archivePos = fdGetCpioPos(iosm->cfd);
2072  if (archivePos > fi->archivePos) {
2073  fi->archivePos = (unsigned long long) archivePos;
2075  fi->archivePos, fi->archiveSize);
2076  }
2077  }
2078 #endif
2079  break;
2080  case IOSM_UNDO:
2081  if (iosm->postpone)
2082  break;
2083  if (iosm->goal == IOSM_PKGINSTALL) {
2084  /* XXX only erase if temp fn w suffix is in use */
2085  if (iosm->sufbuf[0] != '\0')
2086  (void) iosmNext(iosm,
2087  (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK));
2088 
2089 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
2090  if (iosm->dnlx)
2091  (void) iosmNext(iosm, IOSM_RMDIRS);
2092 #endif
2093  errno = saveerrno;
2094  }
2095  if (iosm->failedFile && *iosm->failedFile == NULL)
2096  *iosm->failedFile = xstrdup(iosm->path);
2097  break;
2098  case IOSM_FINI:
2099  if (!iosm->postpone && iosm->commit) {
2100  if (iosm->goal == IOSM_PKGINSTALL)
2101  rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1)
2102  ? iosmCommitLinks(iosm) : iosmNext(iosm, IOSM_COMMIT));
2103  if (iosm->goal == IOSM_PKGCOMMIT)
2104  rc = iosmNext(iosm, IOSM_COMMIT);
2105  if (iosm->goal == IOSM_PKGERASE)
2106  rc = iosmNext(iosm, IOSM_COMMIT);
2107  }
2108  iosm->path = _free(iosm->path);
2109  iosm->lpath = _free(iosm->lpath);
2110  iosm->opath = _free(iosm->opath);
2111  memset(st, 0, sizeof(*st));
2112  memset(ost, 0, sizeof(*ost));
2113  break;
2114  case IOSM_COMMIT:
2115  /* Rename pre-existing modified or unmanaged file. */
2116  if (iosm->osuffix && iosm->diskchecked &&
2117  (iosm->exists || (iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))))
2118  {
2119  const char * opath = iosm->opath;
2120  const char * path = iosm->path;
2121  iosm->opath = iosmFsPath(iosm, st, NULL, NULL);
2122  iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix);
2123  rc = iosmNext(iosm, IOSM_RENAME);
2124  if (!rc) {
2125  rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"),
2126  (iosm->opath ? iosm->opath : ""),
2127  (iosm->path ? iosm->path : ""));
2128  }
2129  iosm->path = _free(iosm->path);
2130  iosm->path = path;
2131  iosm->opath = _free(iosm->opath);
2132  iosm->opath = opath;
2133  }
2134 
2135  /* Remove erased files. */
2136  if (iosm->goal == IOSM_PKGERASE) {
2137  if (iosm->action == FA_ERASE) {
2138  if (S_ISDIR(st->st_mode)) {
2139  rc = iosmNext(iosm, IOSM_RMDIR);
2140  if (!rc) break;
2141  switch (rc) {
2142  case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
2143  case IOSMERR_ENOTEMPTY:
2144  /* XXX make sure that build side permits %missingok on directories. */
2145  if (iosm->fflags & RPMFILE_MISSINGOK)
2146  /*@innerbreak@*/ break;
2147 
2148  /* XXX common error message. */
2149  rpmlog(
2151  _("rmdir of %s failed: Directory not empty\n"),
2152  iosm->path);
2153  /*@innerbreak@*/ break;
2154  default:
2155  rpmlog(
2156  (iosm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG),
2157  _("rmdir of %s failed: %s\n"),
2158  iosm->path, strerror(errno));
2159  /*@innerbreak@*/ break;
2160  }
2161  } else {
2162  rc = iosmNext(iosm, IOSM_UNLINK);
2163  if (!rc) break;
2164  switch (rc) {
2165  case IOSMERR_ENOENT:
2166  if (iosm->fflags & RPMFILE_MISSINGOK)
2167  /*@innerbreak@*/ break;
2168  /*@fallthrough@*/
2169  default:
2170  rpmlog(
2172  _("unlink of %s failed: %s\n"),
2173  iosm->path, strerror(errno));
2174  /*@innerbreak@*/ break;
2175  }
2176  }
2177  }
2178  /* XXX Failure to remove is not (yet) cause for failure. */
2179  if (!iosm->strict_erasures) rc = 0;
2180  break;
2181  }
2182 
2183  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2184  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
2185  if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) {
2186  if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(iosm->path)) {
2187  /* Rename temporary to final file name. */
2188  if (!S_ISDIR(st->st_mode) &&
2189  (iosm->subdir || iosm->suffix || iosm->nsuffix))
2190  {
2191  iosm->opath = iosm->path;
2192  iosm->path = iosmFsPath(iosm, st, NULL, iosm->nsuffix);
2193  rc = iosmNext(iosm, IOSM_RENAME);
2194  if (rc)
2195  (void) Unlink(iosm->opath);
2196  else if (iosm->nsuffix) {
2197  const char * opath = iosmFsPath(iosm, st, NULL, NULL);
2198  rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
2199  (opath ? opath : ""),
2200  (iosm->path ? iosm->path : ""));
2201  opath = _free(opath);
2202  }
2203  iosm->opath = _free(iosm->opath);
2204  }
2205  /*
2206  * Set file security context (if not disabled).
2207  */
2208  if (!rc && !getuid()) {
2209  rc = iosmMapFContext(iosm);
2210  if (!rc)
2211  rc = iosmNext(iosm, IOSM_LSETFCON);
2212  iosm->fcontext = NULL;
2213  }
2214  if (S_ISLNK(st->st_mode)) {
2215  if (!rc && !getuid())
2216  rc = iosmNext(iosm, IOSM_LCHOWN);
2217  } else {
2218  if (!rc && !getuid())
2219  rc = iosmNext(iosm, IOSM_CHOWN);
2220  if (!rc)
2221  rc = iosmNext(iosm, IOSM_CHMOD);
2222  if (!rc) {
2223  time_t mtime = st->st_mtime;
2224  if (fi->fmtimes)
2225  st->st_mtime = fi->fmtimes[iosm->ix];
2226  rc = iosmNext(iosm, IOSM_UTIME);
2227  st->st_mtime = mtime;
2228  }
2229  }
2230  }
2231  }
2232  }
2233 
2234  /* Notify on success. */
2235  if (!rc) rc = iosmNext(iosm, IOSM_NOTIFY);
2236  else if (iosm->failedFile && *iosm->failedFile == NULL) {
2237  *iosm->failedFile = iosm->path;
2238  iosm->path = NULL;
2239  }
2240  break;
2241  case IOSM_DESTROY:
2242  iosm->path = _free(iosm->path);
2243 
2244  /* Check for hard links missing from payload. */
2245  while ((iosm->li = iosm->links) != NULL) {
2246  iosm->links = iosm->li->next;
2247  iosm->li->next = NULL;
2248  if (iosm->goal == IOSM_PKGINSTALL &&
2249  iosm->commit && iosm->li->linksLeft)
2250  {
2251  for (i = 0 ; i < iosm->li->linksLeft; i++) {
2252  if (iosm->li->filex[i] < 0)
2253  /*@innercontinue@*/ continue;
2255  if (iosm->failedFile && *iosm->failedFile == NULL) {
2256  iosm->ix = iosm->li->filex[i];
2257  if (!iosmNext(iosm, IOSM_MAP)) {
2258  *iosm->failedFile = iosm->path;
2259  iosm->path = NULL;
2260  }
2261  }
2262  /*@loopbreak@*/ break;
2263  }
2264  }
2265  if (iosm->goal == IOSM_PKGBUILD &&
2266  (iosm->mapFlags & IOSM_ALL_HARDLINKS))
2267  {
2269  }
2270  freeHardLink(iosm->li); iosm->li = NULL;
2271  }
2272  iosm->ldn = _free(iosm->ldn);
2273  iosm->ldnalloc = iosm->ldnlen = 0;
2274  iosm->rdbuf = iosm->rdb = _free(iosm->rdb);
2275  iosm->wrbuf = iosm->wrb = _free(iosm->wrb);
2276  break;
2277  case IOSM_VERIFY:
2278  if (iosm->diskchecked && !iosm->exists) {
2279  rc = IOSMERR_ENOENT;
2280  break;
2281  }
2282  if (S_ISREG(st->st_mode)) {
2283  char * path = (char *) alloca(strlen(iosm->path) + sizeof("-RPMDELETE"));
2284  (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE");
2285  /*
2286  * XXX HP-UX (and other os'es) don't permit unlink on busy
2287  * XXX files.
2288  */
2289  iosm->opath = iosm->path;
2290  iosm->path = path;
2291  rc = iosmNext(iosm, IOSM_RENAME);
2292  if (!rc)
2293  (void) iosmNext(iosm, IOSM_UNLINK);
2294  else
2295  rc = IOSMERR_UNLINK_FAILED;
2296  iosm->path = iosm->opath;
2297  iosm->opath = NULL;
2298  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2299  /*@notreached@*/ break;
2300  } else if (S_ISDIR(st->st_mode)) {
2301  if (S_ISDIR(ost->st_mode)) return 0;
2302  if (S_ISLNK(ost->st_mode)) {
2303  rc = iosmUNSAFE(iosm, IOSM_STAT);
2304  if (rc == IOSMERR_ENOENT) rc = 0;
2305  if (rc) break;
2306  errno = saveerrno;
2307  if (S_ISDIR(ost->st_mode)) return 0;
2308  }
2309  } else if (S_ISLNK(st->st_mode)) {
2310  if (S_ISLNK(ost->st_mode)) {
2311  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
2312  rc = iosmUNSAFE(iosm, IOSM_READLINK);
2313  errno = saveerrno;
2314  if (rc) break;
2315  if (!strcmp(iosm->lpath, iosm->rdbuf)) return 0;
2316  }
2317  } else if (S_ISFIFO(st->st_mode)) {
2318  if (S_ISFIFO(ost->st_mode)) return 0;
2319  } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
2320  if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
2321  (ost->st_rdev == st->st_rdev)) return 0;
2322  } else if (S_ISSOCK(st->st_mode)) {
2323  if (S_ISSOCK(ost->st_mode)) return 0;
2324  }
2325  /* XXX shouldn't do this with commit/undo. */
2326  rc = 0;
2327  if (iosm->stage == IOSM_PROCESS) rc = iosmNext(iosm, IOSM_UNLINK);
2328  if (rc == 0) rc = IOSMERR_ENOENT;
2329  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2330  /*@notreached@*/ break;
2331 
2332  case IOSM_UNLINK:
2333  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2334  if (iosm->mapFlags & IOSM_SBIT_CHECK) {
2335  struct stat stb;
2336  if (Lstat(iosm->path, &stb) == 0
2337  && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0)
2338  {
2339  /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */
2340  (void)Chmod(iosm->path, stb.st_mode & 0777);
2341  }
2342  }
2343  rc = Unlink(iosm->path);
2344  if (iosm->debug && (stage & IOSM_SYSCALL))
2345  rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur,
2346  iosm->path, (rc < 0 ? strerror(errno) : ""));
2347  if (rc < 0)
2348  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_UNLINK_FAILED);
2349  break;
2350  case IOSM_RENAME:
2351  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2352  if (iosm->mapFlags & IOSM_SBIT_CHECK) {
2353  struct stat stb;
2354  if (Lstat(iosm->path, &stb) == 0
2355  && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0)
2356  {
2357  /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */
2358  (void)Chmod(iosm->path, stb.st_mode & 0777);
2359  }
2360  }
2361  rc = Rename(iosm->opath, iosm->path);
2362  /* XXX Repackaged payloads may be missing files. */
2363  if (iosm->repackaged)
2364  rc = 0;
2365 #if defined(ETXTBSY)
2366  if (rc && errno == ETXTBSY) {
2367  char * path = (char *) alloca(strlen(iosm->path) + sizeof("-RPMDELETE"));
2368  (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE");
2369  /*
2370  * XXX HP-UX (and other os'es) don't permit rename to busy
2371  * XXX files.
2372  */
2373  rc = Rename(iosm->path, path);
2374  if (!rc) rc = Rename(iosm->opath, iosm->path);
2375  }
2376 #endif
2377  if (iosm->debug && (stage & IOSM_SYSCALL))
2378  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2379  iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2380  if (rc < 0) rc = IOSMERR_RENAME_FAILED;
2381  break;
2382  case IOSM_MKDIR:
2383  rc = Mkdir(iosm->path, (st->st_mode & 07777));
2384  if (iosm->debug && (stage & IOSM_SYSCALL))
2385  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2386  iosm->path, (unsigned)(st->st_mode & 07777),
2387  (rc < 0 ? strerror(errno) : ""));
2388  if (rc < 0) rc = IOSMERR_MKDIR_FAILED;
2389  break;
2390  case IOSM_RMDIR:
2391  rc = Rmdir(iosm->path);
2392  if (iosm->debug && (stage & IOSM_SYSCALL))
2393  rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur,
2394  iosm->path, (rc < 0 ? strerror(errno) : ""));
2395  if (rc < 0)
2396  switch (errno) {
2397  case ENOENT: rc = IOSMERR_ENOENT; /*@switchbreak@*/ break;
2398  case ENOTEMPTY: rc = IOSMERR_ENOTEMPTY; /*@switchbreak@*/ break;
2399  default: rc = IOSMERR_RMDIR_FAILED; /*@switchbreak@*/ break;
2400  }
2401  break;
2402  case IOSM_LSETFCON:
2403  { const char * iosmpath = NULL;
2404  if (iosm->fcontext == NULL || *iosm->fcontext == '\0'
2405  || !strcmp(iosm->fcontext, "<<none>>"))
2406  break;
2407  (void) urlPath(iosm->path, &iosmpath); /* XXX iosm->path */
2408  rc = rpmsxLsetfilecon(NULL, iosmpath, 0, iosm->fcontext);
2409  if (iosm->debug && (stage & IOSM_SYSCALL))
2410  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2411  iosm->path, iosm->fcontext,
2412  (rc < 0 ? strerror(errno) : ""));
2413  if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : IOSMERR_LSETFCON_FAILED);
2414  } break;
2415  case IOSM_CHOWN:
2416  rc = Chown(iosm->path, st->st_uid, st->st_gid);
2417  if (iosm->debug && (stage & IOSM_SYSCALL))
2418  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2419  iosm->path, (int)st->st_uid, (int)st->st_gid,
2420  (rc < 0 ? strerror(errno) : ""));
2421  if (rc < 0) rc = IOSMERR_CHOWN_FAILED;
2422  break;
2423  case IOSM_LCHOWN:
2424 #if ! CHOWN_FOLLOWS_SYMLINK
2425  rc = Lchown(iosm->path, st->st_uid, st->st_gid);
2426  if (iosm->debug && (stage & IOSM_SYSCALL))
2427  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2428  iosm->path, (int)st->st_uid, (int)st->st_gid,
2429  (rc < 0 ? strerror(errno) : ""));
2430  if (rc < 0) rc = IOSMERR_CHOWN_FAILED;
2431 #endif
2432  break;
2433  case IOSM_CHMOD:
2434  rc = Chmod(iosm->path, (st->st_mode & 07777));
2435  if (iosm->debug && (stage & IOSM_SYSCALL))
2436  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2437  iosm->path, (unsigned)(st->st_mode & 07777),
2438  (rc < 0 ? strerror(errno) : ""));
2439  if (rc < 0) rc = IOSMERR_CHMOD_FAILED;
2440  break;
2441  case IOSM_UTIME:
2442  { struct utimbuf stamp;
2443  stamp.actime = st->st_mtime;
2444  stamp.modtime = st->st_mtime;
2445  rc = Utime(iosm->path, &stamp);
2446  if (iosm->debug && (stage & IOSM_SYSCALL))
2447  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0x%x) %s\n", cur,
2448  iosm->path, (unsigned)st->st_mtime,
2449  (rc < 0 ? strerror(errno) : ""));
2450  if (rc < 0) rc = IOSMERR_UTIME_FAILED;
2451  }
2452  break;
2453  case IOSM_SYMLINK:
2454  rc = Symlink(iosm->lpath, iosm->path);
2455  if (iosm->debug && (stage & IOSM_SYSCALL))
2456  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2457  iosm->lpath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2458  if (rc < 0) rc = IOSMERR_SYMLINK_FAILED;
2459  break;
2460  case IOSM_LINK:
2461  rc = Link(iosm->opath, iosm->path);
2462  if (iosm->debug && (stage & IOSM_SYSCALL))
2463  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2464  iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2465  if (rc < 0) rc = IOSMERR_LINK_FAILED;
2466  break;
2467  case IOSM_MKFIFO:
2468  rc = Mkfifo(iosm->path, (st->st_mode & 07777));
2469  if (iosm->debug && (stage & IOSM_SYSCALL))
2470  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2471  iosm->path, (unsigned)(st->st_mode & 07777),
2472  (rc < 0 ? strerror(errno) : ""));
2473  if (rc < 0) rc = IOSMERR_MKFIFO_FAILED;
2474  break;
2475  case IOSM_MKNOD:
2476  /*@-unrecog -portability @*/ /* FIX: check S_IFIFO or dev != 0 */
2477  rc = Mknod(iosm->path, (st->st_mode & ~07777), st->st_rdev);
2478  /*@=unrecog =portability @*/
2479  if (iosm->debug && (stage & IOSM_SYSCALL))
2480  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur,
2481  iosm->path, (unsigned)(st->st_mode & ~07777),
2482  (unsigned)st->st_rdev,
2483  (rc < 0 ? strerror(errno) : ""));
2484  if (rc < 0) rc = IOSMERR_MKNOD_FAILED;
2485  break;
2486  case IOSM_LSTAT:
2487  rc = Lstat(iosm->path, ost);
2488  if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT)
2489  rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur,
2490  iosm->path, (rc < 0 ? strerror(errno) : ""));
2491  if (rc < 0) {
2492  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_LSTAT_FAILED);
2493  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2494  }
2495  break;
2496  case IOSM_STAT:
2497  rc = Stat(iosm->path, ost);
2498  if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT)
2499  rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur,
2500  iosm->path, (rc < 0 ? strerror(errno) : ""));
2501  if (rc < 0) {
2502  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_STAT_FAILED);
2503  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2504  }
2505  break;
2506  case IOSM_READLINK:
2507  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
2508  rc = Readlink(iosm->path, iosm->rdbuf, iosm->rdsize - 1);
2509  if (iosm->debug && (stage & IOSM_SYSCALL))
2510  rpmlog(RPMLOG_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur,
2511  iosm->path, (int)(iosm->rdsize -1), (rc < 0 ? strerror(errno) : ""));
2512  if (rc < 0) rc = IOSMERR_READLINK_FAILED;
2513  else {
2514  iosm->rdnb = rc;
2515  iosm->rdbuf[iosm->rdnb] = '\0';
2516  rc = 0;
2517  }
2518  break;
2519  case IOSM_CHROOT:
2520  break;
2521 
2522  case IOSM_NEXT:
2523  rc = iosmUNSAFE(iosm, IOSM_HREAD);
2524  if (rc) break;
2525  if (!strcmp(iosm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */
2526  iosm->path = _free(iosm->path);
2527  rc = IOSMERR_HDR_TRAILER;
2528  }
2529  if (!rc)
2530  rc = iosmNext(iosm, IOSM_POS);
2531  break;
2532  case IOSM_EAT:
2533  for (left = st->st_size; left > 0; left -= iosm->rdnb) {
2534  iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left);
2535  rc = iosmNext(iosm, IOSM_DREAD);
2536  if (rc)
2537  /*@loopbreak@*/ break;
2538  }
2539  break;
2540  case IOSM_POS:
2541  left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize;
2542  if (left) {
2543  iosm->wrlen = left;
2544  (void) iosmNext(iosm, IOSM_DREAD);
2545  }
2546  break;
2547  case IOSM_PAD:
2548  left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize;
2549  if (left) {
2550  if (iosm->blksize == 2)
2551  iosm->rdbuf[0] = '\n'; /* XXX ar(1) pads with '\n' */
2552  else
2553  memset(iosm->rdbuf, 0, left);
2554  /* XXX DWRITE uses rdnb for I/O length. */
2555  iosm->rdnb = left;
2556  (void) iosmNext(iosm, IOSM_DWRITE);
2557  }
2558  break;
2559  case IOSM_TRAILER:
2560  rc = (*iosm->trailerWrite) (iosm); /* Write payload trailer. */
2561  break;
2562  case IOSM_HREAD:
2563  rc = iosmNext(iosm, IOSM_POS);
2564  if (!rc)
2565  rc = (*iosm->headerRead) (iosm, st);/* Read next payload header. */
2566  break;
2567  case IOSM_HWRITE:
2568  rc = (*iosm->headerWrite) (iosm, st); /* Write next payload header. */
2569  break;
2570  case IOSM_DREAD:
2571  iosm->rdnb = Fread(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->wrlen, iosm->cfd);
2572  if (iosm->debug && (stage & IOSM_SYSCALL))
2573  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n",
2574  cur, (iosm->wrbuf == iosm->wrb ? "wrbuf" : "mmap"),
2575  (int)iosm->wrlen, (int)iosm->rdnb);
2576  if (iosm->rdnb != iosm->wrlen || Ferror(iosm->cfd))
2577  rc = IOSMERR_READ_FAILED;
2578  if (iosm->rdnb > 0)
2579  fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->rdnb);
2580  break;
2581  case IOSM_DWRITE:
2582  iosm->wrnb = Fwrite(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdnb, iosm->cfd);
2583  if (iosm->debug && (stage & IOSM_SYSCALL))
2584  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n",
2585  cur, (iosm->rdbuf == iosm->rdb ? "rdbuf" : "mmap"),
2586  (int)iosm->rdnb, (int)iosm->wrnb);
2587  if (iosm->rdnb != iosm->wrnb || Ferror(iosm->cfd))
2588  rc = IOSMERR_WRITE_FAILED;
2589  if (iosm->wrnb > 0)
2590  fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->wrnb);
2591  break;
2592 
2593  case IOSM_ROPEN:
2594  iosm->rfd = Fopen(iosm->path, "r.fdio");
2595  if (iosm->rfd == NULL || Ferror(iosm->rfd)) {
2596  if (iosm->rfd != NULL) (void) iosmNext(iosm, IOSM_RCLOSE);
2597  iosm->rfd = NULL;
2598  rc = IOSMERR_OPEN_FAILED;
2599  break;
2600  }
2601 #if defined(POSIX_FADV_WILLNEED)
2602  (void) Fadvise(iosm->rfd, 0, 0, POSIX_FADV_WILLNEED);
2603 #endif
2604  if (iosm->debug && (stage & IOSM_SYSCALL))
2605  rpmlog(RPMLOG_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur,
2606  iosm->path, iosm->rfd, iosm->rdbuf);
2607  break;
2608  case IOSM_READ:
2609  iosm->rdnb = Fread(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdlen, iosm->rfd);
2610  if (iosm->debug && (stage & IOSM_SYSCALL))
2611  rpmlog(RPMLOG_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n",
2612  cur, (int)iosm->rdlen, (int)iosm->rdnb);
2613  if (iosm->rdnb != iosm->rdlen || Ferror(iosm->rfd))
2614  rc = IOSMERR_READ_FAILED;
2615  break;
2616  case IOSM_RCLOSE:
2617  if (iosm->rfd != NULL) {
2618  if (iosm->debug && (stage & IOSM_SYSCALL))
2619  rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->rfd);
2620  (void) rpmswAdd(&iosm->op_digest,
2621  fdstat_op(iosm->rfd, FDSTAT_DIGEST));
2622  (void) Fclose(iosm->rfd);
2623  errno = saveerrno;
2624  }
2625  iosm->rfd = NULL;
2626  break;
2627  case IOSM_WOPEN:
2628  iosm->wfd = Fopen(iosm->path, "w.fdio");
2629  if (iosm->wfd == NULL || Ferror(iosm->wfd)) {
2630  if (iosm->wfd != NULL) (void) iosmNext(iosm, IOSM_WCLOSE);
2631  iosm->wfd = NULL;
2632  rc = IOSMERR_OPEN_FAILED;
2633  }
2634 #if defined(POSIX_FADV_DONTNEED)
2635  else
2636  (void) Fadvise(iosm->wfd, 0, 0, POSIX_FADV_DONTNEED);
2637 #endif
2638  if (iosm->debug && (stage & IOSM_SYSCALL))
2639  rpmlog(RPMLOG_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur,
2640  iosm->path, iosm->wfd, iosm->wrbuf);
2641  break;
2642  case IOSM_WRITE:
2643  iosm->wrnb = Fwrite(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->rdnb, iosm->wfd);
2644  if (iosm->debug && (stage & IOSM_SYSCALL))
2645  rpmlog(RPMLOG_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n",
2646  cur, (int)iosm->rdnb, (int)iosm->wrnb);
2647  if (iosm->rdnb != iosm->wrnb || Ferror(iosm->wfd))
2648  rc = IOSMERR_WRITE_FAILED;
2649  break;
2650  case IOSM_WCLOSE:
2651  if (iosm->wfd != NULL) {
2652  if (iosm->debug && (stage & IOSM_SYSCALL))
2653  rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->wfd);
2654  (void) rpmswAdd(&iosm->op_digest,
2655  fdstat_op(iosm->wfd, FDSTAT_DIGEST));
2656  (void) Fclose(iosm->wfd);
2657  errno = saveerrno;
2658  }
2659  iosm->wfd = NULL;
2660  break;
2661 
2662  default:
2663  break;
2664  }
2665 
2666  if (!(stage & IOSM_INTERNAL)) {
2667  iosm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc);
2668  }
2669  return rc;
2670 }
2671 /*@=compmempass@*/
2672 
2673 #define IOSM_SKIPPING(_a) \
2674  ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPCOLOR)
2675 
2677 {
2678  return IOSM_SKIPPING(action);
2679 }
2680 
2681 /*@observer@*/ const char * iosmFileActionString(iosmFileAction a)
2682 {
2683  switch (a) {
2684  case FA_UNKNOWN: return "unknown";
2685  case FA_CREATE: return "create";
2686  case FA_COPYOUT: return "copyout";
2687  case FA_COPYIN: return "copyin";
2688  case FA_BACKUP: return "backup";
2689  case FA_SAVE: return "save";
2690  case FA_SKIP: return "skip";
2691  case FA_ALTNAME: return "altname";
2692  case FA_ERASE: return "erase";
2693  case FA_SKIPNSTATE: return "skipnstate";
2694  case FA_SKIPNETSHARED: return "skipnetshared";
2695  case FA_SKIPCOLOR: return "skipcolor";
2696  default: return "???";
2697  }
2698  /*@notreached@*/
2699 }
2700 
2701 /*@observer@*/ const char * iosmFileStageString(iosmFileStage a) {
2702  switch(a) {
2703  case IOSM_UNKNOWN: return "unknown";
2704 
2705  case IOSM_PKGINSTALL:return "INSTALL";
2706  case IOSM_PKGERASE: return "ERASE";
2707  case IOSM_PKGBUILD: return "BUILD";
2708  case IOSM_PKGCOMMIT: return "COMMIT";
2709  case IOSM_PKGUNDO: return "UNDO";
2710 
2711  case IOSM_CREATE: return "create";
2712  case IOSM_INIT: return "init";
2713  case IOSM_MAP: return "map";
2714  case IOSM_MKDIRS: return "mkdirs";
2715  case IOSM_RMDIRS: return "rmdirs";
2716  case IOSM_PRE: return "pre";
2717  case IOSM_PROCESS: return "process";
2718  case IOSM_POST: return "post";
2719  case IOSM_MKLINKS: return "mklinks";
2720  case IOSM_NOTIFY: return "notify";
2721  case IOSM_UNDO: return "undo";
2722  case IOSM_FINI: return "fini";
2723  case IOSM_COMMIT: return "commit";
2724  case IOSM_DESTROY: return "destroy";
2725  case IOSM_VERIFY: return "verify";
2726 
2727  case IOSM_UNLINK: return "Unlink";
2728  case IOSM_RENAME: return "Rename";
2729  case IOSM_MKDIR: return "Mkdir";
2730  case IOSM_RMDIR: return "Rmdir";
2731  case IOSM_LSETFCON: return "lsetfcon";
2732  case IOSM_CHOWN: return "Chown";
2733  case IOSM_LCHOWN: return "Lchown";
2734  case IOSM_CHMOD: return "Chmod";
2735  case IOSM_UTIME: return "Utime";
2736  case IOSM_SYMLINK: return "Symlink";
2737  case IOSM_LINK: return "Link";
2738  case IOSM_MKFIFO: return "Mkfifo";
2739  case IOSM_MKNOD: return "Mknod";
2740  case IOSM_LSTAT: return "Lstat";
2741  case IOSM_STAT: return "Stat";
2742  case IOSM_READLINK: return "Readlink";
2743  case IOSM_CHROOT: return "Chroot";
2744 
2745  case IOSM_NEXT: return "next";
2746  case IOSM_EAT: return "eat";
2747  case IOSM_POS: return "pos";
2748  case IOSM_PAD: return "pad";
2749  case IOSM_TRAILER: return "trailer";
2750  case IOSM_HREAD: return "hread";
2751  case IOSM_HWRITE: return "hwrite";
2752  case IOSM_DREAD: return "Fread";
2753  case IOSM_DWRITE: return "Fwrite";
2754 
2755  case IOSM_ROPEN: return "Fopen";
2756  case IOSM_READ: return "Fread";
2757  case IOSM_RCLOSE: return "Fclose";
2758  case IOSM_WOPEN: return "Fopen";
2759  case IOSM_WRITE: return "Fwrite";
2760  case IOSM_WCLOSE: return "Fclose";
2761 
2762  default: return "???";
2763  }
2764  /*@noteached@*/
2765 }
2766 
2767 char * iosmStrerror(int rc)
2768 {
2769  char msg[256];
2770  const char *s;
2771  int l, myerrno = errno;
2772 
2773  strcpy(msg, "cpio: ");
2774  switch (rc) {
2775  default:
2776  s = msg + strlen(msg);
2777  sprintf((char *)s, _("(error 0x%x)"), (unsigned)rc);
2778  s = NULL;
2779  break;
2780  case IOSMERR_BAD_MAGIC: s = _("Bad magic"); break;
2781  case IOSMERR_BAD_HEADER: s = _("Bad/unreadable header"); break;
2782 
2783  case IOSMERR_OPEN_FAILED: s = "open"; break;
2784  case IOSMERR_CHMOD_FAILED: s = "chmod"; break;
2785  case IOSMERR_CHOWN_FAILED: s = "chown"; break;
2786  case IOSMERR_WRITE_FAILED: s = "write"; break;
2787  case IOSMERR_UTIME_FAILED: s = "utime"; break;
2788  case IOSMERR_UNLINK_FAILED: s = "unlink"; break;
2789  case IOSMERR_RENAME_FAILED: s = "rename"; break;
2790  case IOSMERR_SYMLINK_FAILED: s = "symlink"; break;
2791  case IOSMERR_STAT_FAILED: s = "stat"; break;
2792  case IOSMERR_LSTAT_FAILED: s = "lstat"; break;
2793  case IOSMERR_MKDIR_FAILED: s = "mkdir"; break;
2794  case IOSMERR_RMDIR_FAILED: s = "rmdir"; break;
2795  case IOSMERR_MKNOD_FAILED: s = "mknod"; break;
2796  case IOSMERR_MKFIFO_FAILED: s = "mkfifo"; break;
2797  case IOSMERR_LINK_FAILED: s = "link"; break;
2798  case IOSMERR_READLINK_FAILED: s = "readlink"; break;
2799  case IOSMERR_READ_FAILED: s = "read"; break;
2800  case IOSMERR_COPY_FAILED: s = "copy"; break;
2801  case IOSMERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
2802 
2803  case IOSMERR_HDR_SIZE: s = _("Header size too big"); break;
2804  case IOSMERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
2805  case IOSMERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
2806  case IOSMERR_DIGEST_MISMATCH: s = _("File digest mismatch"); break;
2807  case IOSMERR_INTERNAL: s = _("Internal error"); break;
2808  case IOSMERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
2809  case IOSMERR_ENOENT: s = strerror(ENOENT); break;
2810  case IOSMERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
2811  }
2812 
2813  l = sizeof(msg) - strlen(msg) - 1;
2814  if (s != NULL) {
2815  if (l > 0) strncat(msg, s, l);
2816  l -= strlen(s);
2817  }
2818  if ((rc & IOSMERR_CHECK_ERRNO) && myerrno) {
2819  s = _(" failed - ");
2820  if (l > 0) strncat(msg, s, l);
2821  l -= strlen(s);
2822  if (l > 0) strncat(msg, strerror(myerrno), l);
2823  }
2824  return xstrdup(msg);
2825 }
int arHeaderRead(void *_iosm, struct stat *st)
Read ar(1) header.
Definition: ar.c:92
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
static const char * dnlNextIterator(DNLI_t dnli)
Return next directory name (from file info).
Definition: iosm.c:426
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 xx
Definition: spec.c:744
char * iosmStrerror(int rc)
Return formatted error message on payload handling failure.
Definition: iosm.c:2767
iosmMapFlags cpioMapFlags
Definition: iosm.c:29
iter fi
Definition: fsm.c:170
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
Retrieve operation timestamp from a transaction set.
Definition: pkgio.c:133
enum iosmMapFlags_e iosmMapFlags
int tarTrailerWrite(void *_iosm)
Write cpio trailer to payload.
Definition: tar.c:499
struct rpmmi_s * rpmmi
Database iterator.
Definition: rpmtypes.h:48
struct rpmdb_s * rpmdb
Database of headers and tag value indices.
Definition: rpmtypes.h:43
struct stat sb
Definition: iosm.h:305
rpmlog(RPMLOG_ERR,"%s\n", buf)
struct rpmte_s * rpmte
An element of a transaction set, i.e.
Definition: rpmtypes.h:38
#define _fafilter(_a)
const char * nsuffix
Definition: iosm.h:262
const char ** failedFile
Definition: iosm.h:254
int postpone
Definition: iosm.h:272
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
#define IOSM_VERBOSE
Definition: iosm.h:105
int rpmsxLsetfilecon(rpmsx sx, const char *fn, mode_t mode, const char *scon)
Definition: rpmsx.c:248
static unsigned long long fdGetCpioPos(FD_t fd)
enum iosmFileAction_e iosmFileAction
File disposition(s) during package install/erase processing.
void * alKey
An added/available package retrieval key.
Definition: rpmtypes.h:19
int Symlink(const char *oldpath, const char *newpath)
symlink(3) clone.
Definition: rpmrpc.c:2120
Structures used for an &quot;rpmte&quot; transaction element.
struct rpmPRCO_s * rpmPRCO
Container for commonly extracted dependency set(s).
Definition: rpmtypes.h:33
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
fwrite(3) clone.
Definition: rpmio.c:2432
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
#define _RPMFI_NOMETHODS
Definition: iosm.c:31
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2831
static int iosmMkdirs(IOSM_t iosm)
Create (if necessary) directories not explicitly included in package.
Definition: iosm.c:1473
const char * lpath
Definition: iosm.h:222
Definition: iosm.h:159
static int iosmMapFContext(IOSM_t iosm)
Definition: iosm.c:835
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
Definition: iosm.h:131
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
int rc
Definition: poptALL.c:670
iosmFileAction action
Definition: iosm.h:301
static const char * iosmFsPath(const IOSM_t iosm, const struct stat *st, const char *subdir, const char *suffix)
Build path to file from file info, ornamented with subdir and suffix.
Definition: iosm.c:118
char * wrb
Definition: iosm.h:240
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
const char * path
Definition: iosm.h:220
static void * freeHardLink(struct hardLink_s *li)
Destroy set of hard links.
Definition: iosm.c:564
rpmfi rpmfiUnlink(rpmfi fi, const char *msg)
Unreference a file info set instance.
static int extractRegular(IOSM_t iosm)
Create file from payload stream.
Definition: iosm.c:1028
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
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
rpmuint32_t digestlen
Definition: iosm.h:288
static int mapNextIterator(void *_iter)
Return next index into file info.
Definition: iosm.c:194
FD_t fdLink(void *cookie, const char *msg)
Definition: rpmdb.c:436
static void fdSetCpioPos(FD_t fd, long int cpioPos)
#define reverse(bot, top)
Definition: merge.c:102
#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:2914
int repackaged
Definition: iosm.h:279
size_t lmtaboff
Definition: iosm.h:319
int errno
unsigned int * archiveSize
Definition: iosm.h:252
void * ts
Definition: iosm.h:208
int Link(const char *oldpath, const char *newpath)
link(2) clone.
Definition: rpmrpc.c:345
Structures used for ar(1) archives.
int adding
Definition: iosm.h:282
IOSMI_t iter
Definition: iosm.h:245
int Fadvise(FD_t fd, off_t offset, off_t length, int advice)
posix_fadvise(2) clone.
Definition: rpmrpc.c:1495
static int mapFind(IOSMI_t iter, const char *iosmPath)
Locate archive path in file info.
Definition: iosm.c:247
struct rpmRelocation_s * rpmRelocation
Definition: rpmtypes.h:57
int iosmMapPath(IOSM_t iosm)
Map next file path and action.
Definition: iosm.c:858
int ix
Definition: iosm.h:246
#define S_ISSOCK(mode)
Definition: system.h:655
enum iosmFileStage_e iosmFileStage
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1022
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
IOSM_t freeIOSM(IOSM_t iosm)
Destroy I/O state machine instance.
Definition: iosm.c:580
int Utime(const char *path, const struct utimbuf *buf)
Definition: rpmrpc.c:2021
int cpioHeaderWrite(void *_iosm, struct stat *st)
Write cpio header.
Definition: cpio.c:225
Structures used for cpio(1) archives.
Definition: iosm.h:30
repo _ts
Definition: rpmrepo.c:164
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
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
int(* headerWrite)(void *_iosm, struct stat *st)
Definition: iosm.h:311
sprintf(t," (%u)",(unsigned) dig->nbytes)
size_t wrnb
Definition: iosm.h:243
#define IOSMERR_CHECK_ERRNO
Definition: iosm.h:64
char * alloca()
FD_t cfd
Definition: iosm.h:226
int Chown(const char *path, uid_t owner, gid_t group)
chown(2) clone.
Definition: rpmrpc.c:1674
#define SUFFIX_RPMNEW
Definition: iosm.c:107
struct dnli_s * DNLI_t
Directory name iterator.
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
const char * pos
Definition: rpmrpc.c:501
int i
Definition: fsm.c:274
rpmts rpmtsLink(rpmts ts, const char *msg)
Reference a transaction set instance.
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
assert(key->size==sizeof(hdrNum))
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
int ix
Definition: rpmps-py.c:174
char * p
Definition: macro.c:413
int Rmdir(const char *path)
rmdir(2) clone.
Definition: rpmrpc.c:141
int _iosm_threads
Definition: iosm.c:79
size_t ldnlen
Definition: iosm.h:270
int multithreaded
Definition: iosm.h:281
HE_t ec
Definition: hdrfmt.c:6710
int iosmSetup(IOSM_t iosm, iosmFileStage goal, const char *afmt, const void *_ts, const void *_fi, FD_t cfd, unsigned int *archiveSize, const char **failedFile)
Load external data into I/O state machine.
Definition: iosm.c:669
static void * mapFreeIterator(void *_iter)
Destroy file info iterator.
Definition: iosm.c:150
char sufbuf[64]
Definition: iosm.h:265
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
#define IS_DEV_LOG(_x)
Definition: iosm.c:1629
int gnameToGid(const char *thisGname, gid_t *gid)
Definition: ugid.c:71
FD_t fdFree(FD_t fd, const char *msg)
static int saveHardLink(IOSM_t iosm)
Save hard link in chain.
Definition: iosm.c:478
const char * fdigest
Definition: iosm.h:294
static void * dnlInitIterator(const IOSM_t iosm, int reverse)
Create directory name iterator.
Definition: iosm.c:328
int Rename(const char *oldpath, const char *newpath)
rename(2) clone.
Definition: rpmrpc.c:286
enum pgpHashAlgo_e pgpHashAlgo
9.4.
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
void * fi
Definition: iosm.h:209
#define _IOSM_DEBUG
Definition: iosm.c:73
int Mkdir(const char *path, mode_t mode)
mkdir(2) clone.
Definition: rpmrpc.c:73
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
Definition: rpmrpc.c:1401
static int dnlCount(const DNLI_t dnli)
Definition: iosm.c:306
int rpmsqJoin(void *thread)
Wait for thread to terminate.
Definition: rpmsq.c:671
iosmFileStage stage
Definition: iosm.h:303
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:2676
Structures used for tar(1) archives.
Definition: iosm.h:160
const char * fcontext
Definition: iosm.h:298
int(* trailerWrite)(void *_iosm)
Definition: iosm.h:313
#define IOSM_SYSCALL
Definition: iosm.h:107
#define IOSM_DEAD
Definition: iosm.h:108
static void * dnlFreeIterator(const void *_dnli)
Destroy directory name iterator.
Definition: iosm.c:294
void * rpmtsNotify(rpmts ts, rpmte te, rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total)
Perform transaction progress notify callback.
Definition: rpmts.c:1279
#define SUFFIX_RPMSAVE
Definition: iosm.c:106
The FD_t File Handle data structure.
int rc
Definition: iosm.h:277
struct iosmIterator_s * IOSMI_t
Iterator across package file info, forward on install, backward on erase.
Definition: iosm.h:184
Definition: iosm.h:32
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:113
size_t rdlen
Definition: iosm.h:234
#define _tsmask
int Mknod(const char *path, mode_t mode, dev_t dev)
mknod(3) clone.
Definition: rpmrpc.c:1989
char * rdb
Definition: iosm.h:232
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2410
IOSM_t newIOSM(void)
Create I/O state machine instance.
Definition: iosm.c:574
int iosmStage(IOSM_t iosm, iosmFileStage stage)
File state machine driver.
Definition: iosm.c:1636
void * iosmGetFi(const IOSM_t iosm)
Retrieve transaction element file info from I/O state machine iterator.
Definition: iosm.c:97
int iosmTeardown(IOSM_t iosm)
Clean I/O state machine.
Definition: iosm.c:802
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:2532
spectags st
Definition: spec.c:741
int j
Definition: spec.c:743
int nofcontexts
Definition: iosm.h:285
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
Definition: rpmte.h:37
rpmfi fi
Definition: fsm.c:269
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
#define IOSM_SKIPPING(_a)
Definition: iosm.c:2673
int isave
Definition: fsm.c:273
iosmFileStage nstage
Definition: iosm.h:304
char * wrbuf
Definition: iosm.h:238
int Readlink(const char *path, char *buf, size_t bufsiz)
readlink(2) clone.
Definition: rpmrpc.c:2154
int cpioHeaderRead(void *_iosm, struct stat *st)
Read cpio header.
Definition: cpio.c:96
int iosmMapAttrs(IOSM_t iosm)
Map file stat(2) info.
Definition: iosm.c:949
size_t wrlen
Definition: iosm.h:242
rpmuint32_t fdigestalgo
Definition: iosm.h:287
static void * iter
Create file info iterator.
Definition: fsm.c:168
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2942
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
static int writeLinkedFile(IOSM_t iosm)
Write set of linked files to payload stream.
Definition: iosm.c:1238
return strcmp(ame->name, bme->name)
void * iosmGetTs(const IOSM_t iosm)
Retrieve transaction set from I/O state machine iterator.
const char * s
Definition: poptALL.c:734
static int iosmMakeLinks(IOSM_t iosm)
Create pending hard links to existing file.
Definition: iosm.c:1312
char * t
Definition: rpmds.c:2716
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.
Definition: iosm.h:29
int isave
Definition: iosm.h:211
Definition: iosm.h:161
#define CPIO_TRAILER
Definition: cpio.h:16
char * path
Definition: poptALL.c:744
int arHeaderWrite(void *_iosm, struct stat *st)
Write ar(1) header.
Definition: ar.c:235
char * stpcpy(char *dest, const char *src)
#define IOSM_INTERNAL
Definition: iosm.h:106
if(__progname==NULL)
Definition: poptALL.c:683
te
Definition: macro.c:552
size_t lmtablen
Definition: iosm.h:318
int reverse
Definition: fsm.c:272
struct iosm_s * IOSM_t
File state machine data.
Definition: iosm.h:17
FD_t rfd
Definition: iosm.h:228
rpmtransFlags rpmtsFlags(rpmts ts)
Get transaction flags, i.e.
Definition: rpmts.c:1332
int nofdigests
Definition: iosm.h:284
const char * iosmFileStageString(iosmFileStage a)
Return formatted string representation of file stages.
Definition: iosm.c:2701
struct hardLink_s * links
Definition: iosm.h:248
size_t astriplen
Definition: iosm.h:276
Structures and prototypes used for an &quot;rpmts&quot; transaction set.
Definition: iosm.h:36
#define TAR_BLOCK_SIZE
Definition: tar.h:17
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 Lchown(const char *path, uid_t owner, gid_t group)
lchown(2) clone.
Definition: rpmrpc.c:1735
#define _fi(_a)
Definition: psm.h:30
const char * msg
Definition: rpmts-py.c:976
#define SUFFIX_RPMORIG
Definition: iosm.c:105
size_t rdsize
Definition: iosm.h:233
char * rdbuf
Definition: iosm.h:230
rpmElementType rpmteType(rpmte te)
Retrieve type of transaction element.
Definition: rpmte.c:311
const char * suffix
Definition: iosm.h:264
struct stat osb
Definition: iosm.h:306
unsigned blksize
Definition: iosm.h:308
static int arSetup(IOSM_t iosm, rpmfi fi)
Definition: iosm.c:596
return NULL
Definition: poptALL.c:613
int mkdirsdone
Definition: iosm.h:275
struct Spec_s * Spec
Definition: rpmtypes.h:23
int debug
Definition: iosm.h:283
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2989
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
#define iosmUNSAFE
Definition: iosm.c:23
int _iosm_debug
Definition: iosm.c:75
int Chmod(const char *path, mode_t mode)
chmod(2) clone.
Definition: rpmrpc.c:1765
static void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo, void *datap, size_t *lenp, int asAscii)
File state machine to handle archive I/O and system call&#39;s.
#define _(Text)
Definition: system.h:29
char * b
Definition: macro.c:746
static rpmop fdstat_op(FD_t fd, fdOpX opx)
int
Save source and expand field into target.
Definition: rpmds.c:2709
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
int diskchecked
Definition: iosm.h:273
#define xmalloc
Definition: system.h:32
static int iosmCommitLinks(IOSM_t iosm)
Commit hard linked file set atomically.
Definition: iosm.c:1373
const char * iosmFileActionString(iosmFileAction a)
Return formatted string representation of file disposition.
Definition: iosm.c:2681
static int iosmRmdirs(IOSM_t iosm)
Remove (if created) directories not explicitly included in package.
Definition: iosm.c:1418
static int writeFile(IOSM_t iosm, int writeData)
Write next item to payload stream.
Definition: iosm.c:1100
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 fdno
Definition: rpmts-py.c:923
static int dnlIndex(const DNLI_t dnli)
Definition: iosm.c:314
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
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
int tarHeaderRead(void *_iosm, struct stat *st)
Read tar header from payload.
Definition: tar.c:122
int i
Definition: spec.c:743
int tarHeaderWrite(void *_iosm, struct stat *st)
Write tar header to payload.
Definition: tar.c:387
#define xrealloc
Definition: system.h:35
static int iosmStrCmp(const void *a, const void *b)
Definition: iosm.c:213
File name and stat information.
Definition: iosm.h:218
size_t ldnalloc
Definition: iosm.h:271
int Mkfifo(const char *path, mode_t mode)
mkfifo(3) clone.
Definition: rpmrpc.c:1959
int iosmNext(IOSM_t iosm, iosmFileStage nstage)
File state machine driver.
Definition: iosm.c:461
const unsigned char * digest
Definition: rpmfi-py.c:247
Definition: iosm.h:33
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397
const char * opath
Definition: iosm.h:224