rpm  5.4.15
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 *
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)
815  (void) rpmswAdd(rpmtsOp(iosmGetTs(iosm), RPMTS_OP_DIGEST),
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  ino_t finalInode = (fi->finodes ? (ino_t)fi->finodes[i] : 0);
959  dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0);
960  rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
961  uid_t uid = fi->uid;
962  gid_t gid = fi->gid;
963 
964  /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during
965  installation of _source_ RPMs. Instead, let it use the current
966  run-time owner/group, because most of the time the owner/group in
967  the source RPM (which is the owner/group of the files as staying on
968  the package author system) is not existing on the target system, of
969  course. */
970  if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
971  if (!fi->isSource) {
972  if (iosm->goal == IOSM_PKGINSTALL)
974  _("user %s does not exist - using root\n"), fi->fuser[i]);
975  uid = 0;
976  finalMode &= ~S_ISUID; /* turn off suid bit */
977  }
978  }
979 
980  if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
981  if (!fi->isSource) {
982  if (iosm->goal == IOSM_PKGINSTALL)
984  _("group %s does not exist - using root\n"), fi->fgroup[i]);
985  gid = 0;
986  finalMode &= ~S_ISGID; /* turn off sgid bit */
987  }
988  }
989 
990  if (iosm->mapFlags & IOSM_MAP_MODE)
991  st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
992  if (iosm->mapFlags & IOSM_MAP_TYPE) {
993  st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
994  if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
995  && st->st_nlink == 0)
996  st->st_nlink = 1;
997  st->st_rdev = finalRdev;
998  st->st_ino = finalInode;
999  st->st_mtime = finalMtime;
1000  }
1001  if (iosm->mapFlags & IOSM_MAP_UID)
1002  st->st_uid = uid;
1003  if (iosm->mapFlags & IOSM_MAP_GID)
1004  st->st_gid = gid;
1005 
1006  /*
1007  * Set file digest (if not disabled).
1008  */
1009  if (!iosm->nofdigests) {
1010  iosm->fdigestalgo = fi->digestalgo;
1011  iosm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL);
1012  iosm->digestlen = fi->digestlen;
1013  iosm->digest = (fi->digests ? (fi->digests + (iosm->digestlen * i)) : NULL);
1014  } else {
1015  iosm->fdigestalgo = 0;
1016  iosm->fdigest = NULL;
1017  iosm->digestlen = 0;
1018  iosm->digest = NULL;
1019  }
1020  }
1021  return 0;
1022 }
1023 
1029 /*@-compdef@*/
1030 static int extractRegular(/*@special@*/ IOSM_t iosm)
1031  /*@uses iosm->fdigest, iosm->digest, iosm->sb, iosm->wfd @*/
1032  /*@globals h_errno, fileSystem, internalState @*/
1033  /*@modifies iosm, fileSystem, internalState @*/
1034 {
1035  const struct stat * st = &iosm->sb;
1036  size_t left = (size_t) st->st_size;
1037  int rc = 0;
1038  int xx;
1039 
1040  rc = iosmNext(iosm, IOSM_WOPEN);
1041  if (rc)
1042  goto exit;
1043 
1044  if (st->st_size > 0 && (iosm->fdigest != NULL || iosm->digest != NULL))
1045  fdInitDigest(iosm->wfd, (pgpHashAlgo)iosm->fdigestalgo, 0);
1046 
1047  while (left) {
1048 
1049  iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left);
1050  rc = iosmNext(iosm, IOSM_DREAD);
1051  if (rc)
1052  goto exit;
1053 
1054  rc = iosmNext(iosm, IOSM_WRITE);
1055  if (rc)
1056  goto exit;
1057 
1058  left -= iosm->wrnb;
1059 
1060  /* Notify iff progress, completion is done elsewhere */
1061  if (!rc && left)
1062  (void) iosmNext(iosm, IOSM_NOTIFY);
1063  }
1064 
1065  xx = fsync(Fileno(iosm->wfd));
1066 
1067  if (st->st_size > 0 && (iosm->fdigest || iosm->digest)) {
1068  void * digest = NULL;
1069  int asAscii = (iosm->digest == NULL ? 1 : 0);
1070 
1071  (void) Fflush(iosm->wfd);
1072  fdFiniDigest(iosm->wfd, (pgpHashAlgo)iosm->fdigestalgo, &digest, NULL, asAscii);
1073 
1074  if (digest == NULL) {
1076  goto exit;
1077  }
1078 
1079  if (iosm->digest != NULL) {
1080  if (memcmp(digest, iosm->digest, iosm->digestlen))
1082  } else {
1083  if (strcmp((char *)digest, iosm->fdigest))
1085  }
1086  digest = _free(digest);
1087  }
1088 
1089 exit:
1090  (void) iosmNext(iosm, IOSM_WCLOSE);
1091  return rc;
1092 }
1093 /*@=compdef@*/
1094 
1101 /*@-compdef -compmempass@*/
1102 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t iosm, int writeData)
1103  /*@uses iosm->path, iosm->opath, iosm->sb, iosm->osb, iosm->cfd @*/
1104  /*@globals h_errno, fileSystem, internalState @*/
1105  /*@modifies iosm, fileSystem, internalState @*/
1106 {
1107  const char * path = iosm->path;
1108  const char * opath = iosm->opath;
1109  struct stat * st = &iosm->sb;
1110  struct stat * ost = &iosm->osb;
1111  size_t left;
1112  int xx;
1113  int rc;
1114 
1115  st->st_size = (writeData ? ost->st_size : 0);
1116 
1117  if (S_ISDIR(st->st_mode)) {
1118  st->st_size = 0;
1119  } else if (S_ISLNK(st->st_mode)) {
1120  /*
1121  * While linux puts the size of a symlink in the st_size field,
1122  * I don't think that's a specified standard.
1123  */
1124  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
1125  rc = iosmUNSAFE(iosm, IOSM_READLINK);
1126  if (rc) goto exit;
1127  st->st_size = iosm->rdnb;
1128  iosm->lpath = xstrdup(iosm->rdbuf); /* XXX save readlink return. */
1129  }
1130 
1131  if (iosm->mapFlags & IOSM_MAP_ABSOLUTE) {
1132  size_t nb=strlen(iosm->dirName) + strlen(iosm->baseName) + sizeof(".");
1133  char * t = (char *) alloca(nb);
1134  *t = '\0';
1135  iosm->path = t;
1136  if (iosm->mapFlags & IOSM_MAP_ADDDOT)
1137  *t++ = '.';
1138  t = stpcpy( stpcpy(t, iosm->dirName), iosm->baseName);
1139  } else if (iosm->mapFlags & IOSM_MAP_PATH) {
1140  rpmfi fi = (rpmfi) iosmGetFi(iosm);
1141  if (fi->apath) {
1142  const char * apath = NULL;
1143  (void) urlPath(fi->apath[iosm->ix], &apath);
1144  iosm->path = apath + fi->striplen;
1145  } else
1146  iosm->path = fi->bnl[iosm->ix];
1147  }
1148 
1149  rc = iosmNext(iosm, IOSM_HWRITE);
1150  iosm->path = path;
1151  if (rc) goto exit;
1152 
1153  if (writeData && S_ISREG(st->st_mode)) {
1154 #if defined(HAVE_MMAP)
1155  char * rdbuf = NULL;
1156  void * mapped = (void *)-1;
1157  size_t nmapped = 0;
1158  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */
1159  int use_mmap = (st->st_size <= 0x07ffffff);
1160 #endif
1161 
1162  rc = iosmNext(iosm, IOSM_ROPEN);
1163  if (rc) goto exit;
1164 
1165  /* XXX unbuffered mmap generates *lots* of fdio debugging */
1166 #if defined(HAVE_MMAP)
1167  if (use_mmap) {
1168  mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(iosm->rfd), 0);
1169  if (mapped != (void *)-1) {
1170  rdbuf = iosm->rdbuf;
1171  iosm->rdbuf = (char *) mapped;
1172  iosm->rdlen = nmapped = st->st_size;
1173 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1174  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1175 #endif
1176  }
1177  }
1178 #endif
1179 
1180  left = st->st_size;
1181 
1182  while (left) {
1183 #if defined(HAVE_MMAP)
1184  if (mapped != (void *)-1) {
1185  iosm->rdnb = nmapped;
1186  } else
1187 #endif
1188  {
1189  iosm->rdlen = (left > iosm->rdsize ? iosm->rdsize : left),
1190  rc = iosmNext(iosm, IOSM_READ);
1191  if (rc) goto exit;
1192  }
1193 
1194  /* XXX DWRITE uses rdnb for I/O length. */
1195  rc = iosmNext(iosm, IOSM_DWRITE);
1196  if (rc) goto exit;
1197 
1198  left -= iosm->wrnb;
1199  }
1200 
1201 #if defined(HAVE_MMAP)
1202  if (mapped != (void *)-1) {
1203 /* XXX splint misses size_t 2nd arg. */
1204 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC);
1205 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
1206  xx = madvise(mapped, nmapped, MADV_DONTNEED);
1207 #endif
1208  xx = munmap(mapped, nmapped);
1209  iosm->rdbuf = rdbuf;
1210  } else
1211 #endif
1212  { int fdno = Fileno(iosm->rfd);
1213  if (fdno >= 0)
1214  xx = fsync(fdno); /* XXX coverity #1035827 */
1215  }
1216 
1217  }
1218 
1219  rc = iosmNext(iosm, IOSM_PAD);
1220  if (rc) goto exit;
1221 
1222  rc = 0;
1223 
1224 exit:
1225  if (iosm->rfd != NULL)
1226  (void) iosmNext(iosm, IOSM_RCLOSE);
1227 /*@-dependenttrans@*/
1228  iosm->opath = opath;
1229  iosm->path = path;
1230 /*@=dependenttrans@*/
1231  return rc;
1232 }
1233 /*@=compdef =compmempass@*/
1234 
1240 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1241  /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->li, iosm->failedFile @*/
1242  /*@globals h_errno, fileSystem, internalState @*/
1243  /*@modifies iosm, fileSystem, internalState @*/
1244 {
1245  const char * path = iosm->path;
1246  const char * lpath = iosm->lpath;
1247  const char * nsuffix = iosm->nsuffix;
1248  int iterIndex = iosm->ix;
1249  int ec = 0;
1250  int rc;
1251  int i;
1252  const char * linkpath = NULL;
1253  int firstfile = 1;
1254 
1255  iosm->path = NULL;
1256  iosm->lpath = NULL;
1257  iosm->nsuffix = NULL;
1258  iosm->ix = -1;
1259 
1260  for (i = iosm->li->nlink - 1; i >= 0; i--) {
1261 
1262  if (iosm->li->filex[i] < 0) continue;
1263 
1264  iosm->ix = iosm->li->filex[i];
1265 /*@-compdef@*/
1266  rc = iosmNext(iosm, IOSM_MAP);
1267 /*@=compdef@*/
1268 
1269  /* XXX tar and cpio have to do things differently. */
1270  if (iosm->headerWrite == tarHeaderWrite) {
1271  if (firstfile) {
1272  const char * apath = NULL;
1273  char *t;
1274  (void) urlPath(iosm->path, &apath);
1275  /* Remove the buildroot prefix. */
1276  t = (char *) xmalloc(sizeof(".") + strlen(apath + iosm->astriplen));
1277  (void) stpcpy( stpcpy(t, "."), apath + iosm->astriplen);
1278  linkpath = t;
1279  firstfile = 0;
1280  } else
1281  iosm->lpath = linkpath;
1282 
1283  /* Write data after first link for tar. */
1284  rc = writeFile(iosm, (iosm->lpath == NULL));
1285  } else {
1286  /* Write data after last link for cpio. */
1287  rc = writeFile(iosm, (i == 0));
1288  }
1289  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1290  ec = rc;
1291  *iosm->failedFile = xstrdup(iosm->path);
1292  }
1293 
1294  iosm->path = _free(iosm->path);
1295  iosm->li->filex[i] = -1;
1296  }
1297 
1298 /*@-dependenttrans@*/
1299  linkpath = _free(linkpath);
1300 /*@=dependenttrans@*/
1301  iosm->ix = iterIndex;
1302  iosm->nsuffix = nsuffix;
1303  iosm->lpath = lpath;
1304  iosm->path = path;
1305  return ec;
1306 }
1307 
1313 /*@-compdef@*/
1314 static int iosmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1315  /*@uses iosm->path, iosm->opath, iosm->nsuffix, iosm->ix, iosm->li @*/
1316  /*@globals h_errno, fileSystem, internalState @*/
1317  /*@modifies iosm, fileSystem, internalState @*/
1318 {
1319  const char * path = iosm->path;
1320  const char * opath = iosm->opath;
1321  const char * nsuffix = iosm->nsuffix;
1322  int iterIndex = iosm->ix;
1323  int ec = 0;
1324  int rc;
1325  int i;
1326 
1327  iosm->path = NULL;
1328  iosm->opath = NULL;
1329  iosm->nsuffix = NULL;
1330  iosm->ix = -1;
1331 
1332  iosm->ix = iosm->li->filex[iosm->li->createdPath];
1333  rc = iosmNext(iosm, IOSM_MAP);
1334  iosm->opath = iosm->path;
1335  iosm->path = NULL;
1336  for (i = 0; i < iosm->li->nlink; i++) {
1337  if (iosm->li->filex[i] < 0) continue;
1338  if (iosm->li->createdPath == i) continue;
1339 
1340  iosm->ix = iosm->li->filex[i];
1341  iosm->path = _free(iosm->path);
1342  rc = iosmNext(iosm, IOSM_MAP);
1343  if (iosmFileActionSkipped(iosm->action)) continue;
1344 
1345  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
1346  if (!rc) continue;
1347  if (!(rc == IOSMERR_ENOENT)) break;
1348 
1349  /* XXX link(iosm->opath, iosm->path) */
1350  rc = iosmNext(iosm, IOSM_LINK);
1351  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1352  ec = rc;
1353  *iosm->failedFile = xstrdup(iosm->path);
1354  }
1355 
1356  iosm->li->linksLeft--;
1357  }
1358  iosm->path = _free(iosm->path);
1359  iosm->opath = _free(iosm->opath);
1360 
1361  iosm->ix = iterIndex;
1362  iosm->nsuffix = nsuffix;
1363  iosm->path = path;
1364  iosm->opath = opath;
1365  return ec;
1366 }
1367 /*@=compdef@*/
1368 
1374 /*@-compdef@*/
1375 static int iosmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1376  /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->sb,
1377  iosm->li, iosm->links @*/
1378  /*@globals h_errno, fileSystem, internalState @*/
1379  /*@modifies iosm, fileSystem, internalState @*/
1380 {
1381  const char * path = iosm->path;
1382  const char * nsuffix = iosm->nsuffix;
1383  int iterIndex = iosm->ix;
1384  struct stat * st = &iosm->sb;
1385  int rc = 0;
1386  int i;
1387 
1388  iosm->path = NULL;
1389  iosm->nsuffix = NULL;
1390  iosm->ix = -1;
1391 
1392  for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li->next) {
1393  if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == st->st_dev)
1394  break;
1395  }
1396 
1397 assert(iosm->li); /* XXX coverity #1035793 */
1398  for (i = 0; i < iosm->li->nlink; i++) {
1399  if (iosm->li->filex[i] < 0) continue;
1400  iosm->ix = iosm->li->filex[i];
1401  rc = iosmNext(iosm, IOSM_MAP);
1402  if (!iosmFileActionSkipped(iosm->action))
1403  rc = iosmNext(iosm, IOSM_COMMIT);
1404  iosm->path = _free(iosm->path);
1405  iosm->li->filex[i] = -1;
1406  }
1407 
1408  iosm->ix = iterIndex;
1409  iosm->nsuffix = nsuffix;
1410  iosm->path = path;
1411  return rc;
1412 }
1413 /*@=compdef@*/
1414 
1420 static int iosmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1421  /*@uses iosm->path, iosm->dnlx, iosm->ldn, iosm->rdbuf, iosm->iter @*/
1422  /*@globals h_errno, fileSystem, internalState @*/
1423  /*@modifies iosm, fileSystem, internalState @*/
1424 {
1425  const char * path = iosm->path;
1426  void * dnli = dnlInitIterator(iosm, 1);
1427  char * dn = iosm->rdbuf;
1428  int dc = dnlCount((DNLI_t)dnli);
1429  int rc = 0;
1430 
1431  iosm->path = NULL;
1432  dn[0] = '\0';
1433  /*@-observertrans -dependenttrans@*/
1434  if (iosm->ldn != NULL && iosm->dnlx != NULL)
1435  while ((iosm->path = dnlNextIterator((DNLI_t)dnli)) != NULL) {
1436  size_t dnlen = strlen(iosm->path);
1437  char * te;
1438 
1439  dc = dnlIndex((DNLI_t)dnli);
1440  if (iosm->dnlx[dc] < 1 || (size_t)iosm->dnlx[dc] >= dnlen)
1441  continue;
1442 
1443  /* Copy to avoid const on iosm->path. */
1444  te = stpcpy(dn, iosm->path) - 1;
1445  iosm->path = dn;
1446 
1447  /* Remove generated directories. */
1448  /*@-usereleased@*/ /* LCL: te used after release? */
1449  do {
1450  if (*te == '/') {
1451  *te = '\0';
1452 /*@-compdef@*/
1453  rc = iosmNext(iosm, IOSM_RMDIR);
1454 /*@=compdef@*/
1455  *te = '/';
1456  }
1457  if (rc)
1458  /*@innerbreak@*/ break;
1459  te--;
1460  } while ((te - iosm->path) > iosm->dnlx[dc]);
1461  /*@=usereleased@*/
1462  }
1463  dnli = dnlFreeIterator(dnli);
1464  /*@=observertrans =dependenttrans@*/
1465 
1466  iosm->path = path;
1467  return rc;
1468 }
1469 
1475 static int iosmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1476  /*@uses iosm->path, iosm->sb, iosm->osb, iosm->rdbuf, iosm->iter,
1477  iosm->ldn, iosm->ldnlen, iosm->ldnalloc @*/
1478  /*@defines iosm->dnlx, iosm->ldn @*/
1479  /*@globals h_errno, fileSystem, internalState @*/
1480  /*@modifies iosm, fileSystem, internalState @*/
1481 {
1482  struct stat * st = &iosm->sb;
1483  struct stat * ost = &iosm->osb;
1484  const char * path = iosm->path;
1485  mode_t st_mode = st->st_mode;
1486  void * dnli = dnlInitIterator(iosm, 0);
1487  char * dn = iosm->rdbuf;
1488  int dc = dnlCount((DNLI_t)dnli);
1489  int rc = 0;
1490  size_t i;
1491 
1492  iosm->path = NULL;
1493 
1494  dn[0] = '\0';
1495  iosm->dnlx = (unsigned short *) (dc ? xcalloc(dc, sizeof(*iosm->dnlx)) : NULL);
1496  /*@-observertrans -dependenttrans@*/
1497  if (iosm->dnlx != NULL)
1498  while ((iosm->path = dnlNextIterator((DNLI_t)dnli)) != NULL) {
1499  size_t dnlen = strlen(iosm->path);
1500  char * te;
1501 
1502  dc = dnlIndex((DNLI_t)dnli);
1503  if (dc < 0) continue;
1504  iosm->dnlx[dc] = (unsigned short) dnlen;
1505  if (dnlen <= 1)
1506  continue;
1507 
1508  /*@-compdef -nullpass@*/ /* FIX: iosm->ldn not defined ??? */
1509  if (dnlen <= iosm->ldnlen && !strcmp(iosm->path, iosm->ldn))
1510  continue;
1511  /*@=compdef =nullpass@*/
1512 
1513  /* Copy to avoid const on iosm->path. */
1514  (void) stpcpy(dn, iosm->path);
1515  iosm->path = dn;
1516 
1517  /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
1518  (void) urlPath(dn, (const char **)&te);
1519  for (i = 1, te++; *te != '\0'; te++, i++) {
1520  if (*te != '/')
1521  /*@innercontinue@*/ continue;
1522 
1523  *te = '\0';
1524 
1525  /* Already validated? */
1526  /*@-usedef -compdef -nullpass -nullderef@*/
1527  if (i < iosm->ldnlen &&
1528  (iosm->ldn[i] == '/' || iosm->ldn[i] == '\0') &&
1529  !strncmp(iosm->path, iosm->ldn, i))
1530  {
1531  *te = '/';
1532  /* Move pre-existing path marker forward. */
1533  iosm->dnlx[dc] = (te - dn);
1534  /*@innercontinue@*/ continue;
1535  }
1536  /*@=usedef =compdef =nullpass =nullderef@*/
1537 
1538  /* Validate next component of path. */
1539  rc = iosmUNSAFE(iosm, IOSM_LSTAT);
1540  *te = '/';
1541 
1542  /* Directory already exists? */
1543  if (rc == 0 && S_ISDIR(ost->st_mode)) {
1544  /* Move pre-existing path marker forward. */
1545  iosm->dnlx[dc] = (te - dn);
1546  } else if (rc == IOSMERR_ENOENT) {
1547  rpmfi fi = (rpmfi) iosmGetFi(iosm);
1548  *te = '\0';
1549  st->st_mode = S_IFDIR | (fi->dperms & 07777);
1550  rc = iosmNext(iosm, IOSM_MKDIR);
1551  if (!rc) {
1552 #if defined(_USE_RPMSX)
1553  /* XXX FIXME? only new dir will have context set. */
1554  /* Get file security context from patterns. */
1555  if (!fsm->nofcontexts) {
1556  iosm->fcontext =
1557  rpmsxMatch(NULL, iosm->path, st->st_mode);
1558  if (iosm->fcontext != NULL)
1559  rc = iosmNext(iosm, IOSM_LSETFCON);
1560  } else
1561 #endif
1562  iosm->fcontext = NULL;
1564  D_("%s directory created with perms %04o, context %s.\n"),
1565  iosm->path, (unsigned)(st->st_mode & 07777),
1566  (iosm->fcontext ? iosm->fcontext : "(no context)"));
1567 #if defined(_USE_RPMSX)
1568  iosm->fcontext = _free(iosm->fcontext);
1569 #endif
1570  }
1571  *te = '/';
1572  }
1573  if (rc)
1574  /*@innerbreak@*/ break;
1575  }
1576  if (rc) break;
1577 
1578  /* Save last validated path. */
1579 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1580  if (iosm->ldnalloc < (dnlen + 1)) {
1581  iosm->ldnalloc = dnlen + 100;
1582  iosm->ldn = (char *) xrealloc(iosm->ldn, iosm->ldnalloc);
1583  }
1584  if (iosm->ldn != NULL) { /* XXX can't happen */
1585  strcpy(iosm->ldn, iosm->path);
1586  iosm->ldnlen = dnlen;
1587  }
1588 /*@=compdef@*/
1589  }
1590  dnli = dnlFreeIterator(dnli);
1591  /*@=observertrans =dependenttrans@*/
1592 
1593  iosm->path = path;
1594  st->st_mode = st_mode; /* XXX restore st->st_mode */
1595 /*@-compdef@*/ /* FIX: ldn/path annotations ? */
1596  return rc;
1597 /*@=compdef@*/
1598 }
1599 
1600 #ifdef NOTYET
1601 
1606 static int iosmStat(/*@special@*/ /*@partial@*/ IOSM_t iosm)
1607  /*@globals fileSystem, internalState @*/
1608  /*@modifies iosm, fileSystem, internalState @*/
1609 {
1610  int rc = 0;
1611 
1612  if (iosm->path != NULL) {
1613  int saveernno = errno;
1614  rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1615  ? IOSM_LSTAT : IOSM_STAT));
1616  if (rc == IOSMERR_ENOENT) {
1617  errno = saveerrno;
1618  rc = 0;
1619  iosm->exists = 0;
1620  } else if (rc == 0) {
1621  iosm->exists = 1;
1622  }
1623  } else {
1624  /* Skip %ghost files on build. */
1625  iosm->exists = 0;
1626  }
1627  return rc;
1628 }
1629 #endif
1630 
1631 #define IS_DEV_LOG(_x) \
1632  ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
1633  !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
1634  ((_x)[sizeof("/dev/log")-1] == '\0' || \
1635  (_x)[sizeof("/dev/log")-1] == ';'))
1636 
1637 /*@-compmempass@*/
1639 {
1640 #ifdef NOTUSED
1641  iosmFileStage prevStage = iosm->stage;
1642  const char * const prev = iosmFileStageString(prevStage);
1643 #endif
1644  const char * const cur = iosmFileStageString(stage);
1645  struct stat * st = &iosm->sb;
1646  struct stat * ost = &iosm->osb;
1647  int saveerrno = errno;
1648  int rc = iosm->rc;
1649  size_t left;
1650  int i;
1651 
1652 #define _fafilter(_a) \
1653  (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
1654  ? iosmFileActionString(_a) : "")
1655 
1656  if (stage & IOSM_DEAD) {
1657  /* do nothing */
1658  } else if (stage & IOSM_INTERNAL) {
1659  if (iosm->debug && !(stage & IOSM_SYSCALL))
1660  rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1661  cur,
1662  (unsigned)st->st_mode, (int)st->st_nlink,
1663  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1664  (iosm->path ? iosm->path : ""),
1665  _fafilter(iosm->action));
1666  } else {
1667  const char * apath = NULL;
1668  if (iosm->path)
1669  (void) urlPath(iosm->path, &apath);
1670  iosm->stage = stage;
1671  if (iosm->debug || !(stage & IOSM_VERBOSE))
1672  rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n",
1673  cur,
1674  (unsigned)st->st_mode, (int)st->st_nlink,
1675  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
1676  (apath ? apath + iosm->astriplen : ""),
1677  _fafilter(iosm->action));
1678  }
1679 #undef _fafilter
1680 
1681  switch (stage) {
1682  case IOSM_UNKNOWN:
1683  break;
1684  case IOSM_PKGINSTALL:
1685  while (1) {
1686  /* Clean iosm, free'ing memory. Read next archive header. */
1687  rc = iosmUNSAFE(iosm, IOSM_INIT);
1688 
1689  /* Exit on end-of-payload. */
1690  if (rc == IOSMERR_HDR_TRAILER) {
1691  rc = 0;
1692  /*@loopbreak@*/ break;
1693  }
1694 
1695  /* Exit on error. */
1696  if (rc) {
1697  iosm->postpone = 1;
1698  (void) iosmNext(iosm, IOSM_UNDO);
1699  /*@loopbreak@*/ break;
1700  }
1701 
1702  /* Extract file from archive. */
1703  rc = iosmNext(iosm, IOSM_PROCESS);
1704  if (rc) {
1705  (void) iosmNext(iosm, IOSM_UNDO);
1706  /*@loopbreak@*/ break;
1707  }
1708 
1709  /* Notify on success. */
1710  (void) iosmNext(iosm, IOSM_NOTIFY);
1711 
1712  rc = iosmNext(iosm, IOSM_FINI);
1713  if (rc) {
1714  /*@loopbreak@*/ break;
1715  }
1716  }
1717  break;
1718  case IOSM_PKGERASE:
1719  case IOSM_PKGCOMMIT:
1720  while (1) {
1721  /* Clean iosm, free'ing memory. */
1722  rc = iosmUNSAFE(iosm, IOSM_INIT);
1723 
1724  /* Exit on end-of-payload. */
1725  if (rc == IOSMERR_HDR_TRAILER) {
1726  rc = 0;
1727  /*@loopbreak@*/ break;
1728  }
1729 
1730  /* Rename/erase next item. */
1731  if (iosmNext(iosm, IOSM_FINI))
1732  /*@loopbreak@*/ break;
1733  }
1734  break;
1735  case IOSM_PKGBUILD:
1736  while (1) {
1737 
1738  rc = iosmUNSAFE(iosm, IOSM_INIT);
1739 
1740  /* Exit on end-of-payload. */
1741  if (rc == IOSMERR_HDR_TRAILER) {
1742  rc = 0;
1743  /*@loopbreak@*/ break;
1744  }
1745 
1746  /* Exit on error. */
1747  if (rc) {
1748  iosm->postpone = 1;
1749  (void) iosmNext(iosm, IOSM_UNDO);
1750  /*@loopbreak@*/ break;
1751  }
1752 
1753  /* Copy file into archive. */
1754  rc = iosmNext(iosm, IOSM_PROCESS);
1755  if (rc) {
1756  (void) iosmNext(iosm, IOSM_UNDO);
1757  /*@loopbreak@*/ break;
1758  }
1759 
1760  /* Notify on success. */
1761  (void) iosmNext(iosm, IOSM_NOTIFY);
1762 
1763  if (iosmNext(iosm, IOSM_FINI))
1764  /*@loopbreak@*/ break;
1765  }
1766 
1767  /* Flush partial sets of hard linked files. */
1768  if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) {
1769  int nlink, j;
1770  while ((iosm->li = iosm->links) != NULL) {
1771  iosm->links = iosm->li->next;
1772  iosm->li->next = NULL;
1773 
1774  /* Re-calculate link count for archive header. */
1775  for (j = -1, nlink = 0, i = 0; i < iosm->li->nlink; i++) {
1776  if (iosm->li->filex[i] < 0)
1777  /*@innercontinue@*/ continue;
1778  nlink++;
1779  if (j == -1) j = i;
1780  }
1781  /* XXX force the contents out as well. */
1782  if (j != 0) {
1783  iosm->li->filex[0] = iosm->li->filex[j];
1784  iosm->li->filex[j] = -1;
1785  }
1786  iosm->li->sb.st_nlink = nlink;
1787 
1788  iosm->sb = iosm->li->sb; /* structure assignment */
1789  iosm->osb = iosm->sb; /* structure assignment */
1790 
1791  if (!rc) rc = writeLinkedFile(iosm);
1792 
1793  iosm->li = (struct hardLink_s *) freeHardLink((struct hardLink_s *) iosm->li);
1794  }
1795  }
1796 
1797  if (!rc)
1798  rc = iosmNext(iosm, IOSM_TRAILER);
1799 
1800  break;
1801  case IOSM_CREATE:
1802  iosm->path = _free(iosm->path);
1803  iosm->lpath = _free(iosm->lpath);
1804  iosm->opath = _free(iosm->opath);
1805  iosm->dnlx = _free(iosm->dnlx);
1806 
1807  iosm->ldn = _free(iosm->ldn);
1808  iosm->ldnalloc = iosm->ldnlen = 0;
1809 
1810  iosm->rdsize = iosm->wrsize = 0;
1811  iosm->rdbuf = iosm->rdb = _free(iosm->rdb);
1812  iosm->wrbuf = iosm->wrb = _free(iosm->wrb);
1813  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
1814  iosm->rdsize = 16 * BUFSIZ;
1815  iosm->rdbuf = iosm->rdb = (char *) xmalloc(iosm->rdsize);
1816  iosm->wrsize = 16 * BUFSIZ;
1817  iosm->wrbuf = iosm->wrb = (char *) xmalloc(iosm->wrsize);
1818  }
1819 
1820  iosm->mkdirsdone = 0;
1821  iosm->ix = -1;
1822  iosm->links = NULL;
1823  iosm->li = NULL;
1824  errno = 0; /* XXX get rid of EBADF */
1825 
1826  /* Detect and create directories not explicitly in package. */
1827  if (iosm->goal == IOSM_PKGINSTALL) {
1828 /*@-compdef@*/
1829  rc = iosmNext(iosm, IOSM_MKDIRS);
1830 /*@=compdef@*/
1831  if (!rc) iosm->mkdirsdone = 1;
1832  }
1833 
1834  break;
1835  case IOSM_INIT:
1836  iosm->path = _free(iosm->path);
1837  iosm->lpath = _free(iosm->lpath);
1838  iosm->postpone = 0;
1839  iosm->diskchecked = iosm->exists = 0;
1840  iosm->subdir = NULL;
1841  iosm->suffix = (iosm->sufbuf[0] != '\0' ? iosm->sufbuf : NULL);
1842  iosm->action = FA_UNKNOWN;
1843  iosm->osuffix = NULL;
1844  iosm->nsuffix = NULL;
1845 
1846  if (iosm->goal == IOSM_PKGINSTALL) {
1847  /* Read next header from payload, checking for end-of-payload. */
1848  rc = iosmUNSAFE(iosm, IOSM_NEXT);
1849  }
1850  if (rc) break;
1851 
1852  /* Identify mapping index. */
1853  iosm->ix = ((iosm->goal == IOSM_PKGINSTALL)
1854  ? mapFind(iosm->iter, iosm->path) : mapNextIterator(iosm->iter));
1855 
1856  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
1857  if (fi != NULL && !(fi->mapflags & IOSM_PAYLOAD_LIST)) {
1858  /* Detect end-of-loop and/or mapping error. */
1859  if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) {
1860  if (iosm->ix < 0) {
1861  if (iosm->goal == IOSM_PKGINSTALL) {
1862 #if 0
1864  _("archive file %s was not found in header\n"),
1865  iosm->path);
1866 #endif
1867  if (iosm->failedFile && *iosm->failedFile == NULL)
1868  *iosm->failedFile = xstrdup(iosm->path);
1869  rc = IOSMERR_UNMAPPED_FILE;
1870  } else
1871  rc = IOSMERR_HDR_TRAILER;
1872  break;
1873  }
1874  }
1875 
1876  /* On non-install, mode must be known so dirs don't get suffixed. */
1877  if (iosm->goal != IOSM_PKGINSTALL)
1878  st->st_mode = fi->fmodes[iosm->ix];
1879  }
1880  }
1881 
1882  /* Generate file path. */
1883  rc = iosmNext(iosm, IOSM_MAP);
1884  if (rc) break;
1885 
1886  /* Perform lstat/stat for disk file. */
1887 #ifdef NOTYET
1888  rc = iosmStat(iosm);
1889 #else
1890  if (iosm->path != NULL &&
1891  !(iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))
1892  {
1893  rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS)
1894  ? IOSM_LSTAT : IOSM_STAT));
1895  if (rc == IOSMERR_ENOENT) {
1896  errno = saveerrno;
1897  rc = 0;
1898  iosm->exists = 0;
1899  } else if (rc == 0) {
1900  iosm->exists = 1;
1901  }
1902  } else {
1903  /* Skip %ghost files on build. */
1904  iosm->exists = 0;
1905  }
1906 #endif
1907  iosm->diskchecked = 1;
1908  if (rc) break;
1909 
1910  /* On non-install, the disk file stat is what's remapped. */
1911  if (iosm->goal != IOSM_PKGINSTALL)
1912  *st = *ost; /* structure assignment */
1913 
1914  /* Remap file perms, owner, and group. */
1915  rc = iosmMapAttrs(iosm);
1916  if (rc) break;
1917 
1918  iosm->postpone = iosmFileActionSkipped(iosm->action);
1919  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
1920  /*@-evalorder@*/ /* FIX: saveHardLink can modify iosm */
1921  if (S_ISREG(st->st_mode) && st->st_nlink > 1)
1922  iosm->postpone = saveHardLink(iosm);
1923  /*@=evalorder@*/
1924  }
1925  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
1926  if (fi != NULL && (fi->mapflags & IOSM_PAYLOAD_LIST))
1927  iosm->postpone = 1;
1928  }
1929  break;
1930  case IOSM_PRE:
1931  break;
1932  case IOSM_MAP:
1933  rc = iosmMapPath(iosm);
1934  break;
1935  case IOSM_MKDIRS:
1936  rc = iosmMkdirs(iosm);
1937  break;
1938  case IOSM_RMDIRS:
1939  if (iosm->dnlx)
1940  rc = iosmRmdirs(iosm);
1941  break;
1942  case IOSM_PROCESS:
1943  if (iosm->postpone) {
1944  if (iosm->goal == IOSM_PKGINSTALL) {
1945  /* XXX Skip over file body, archive headers already done. */
1946  if (S_ISREG(st->st_mode))
1947  rc = iosmNext(iosm, IOSM_EAT);
1948  }
1949  break;
1950  }
1951 
1952  if (iosm->goal == IOSM_PKGBUILD) {
1953  if (iosm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
1954  break;
1955  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
1956  struct hardLink_s * li, * prev;
1957 
1958 if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) break;
1959  rc = writeLinkedFile(iosm);
1960  if (rc) break; /* W2DO? */
1961 
1962  for (li = iosm->links, prev = NULL; li; prev = li, li = li->next)
1963  if (li == iosm->li)
1964  /*@loopbreak@*/ break;
1965 
1966  if (prev == NULL)
1967  iosm->links = iosm->li->next;
1968  else
1969  prev->next = iosm->li->next;
1970  iosm->li->next = NULL;
1971  iosm->li = (struct hardLink_s *) freeHardLink((struct hardLink_s *) iosm->li);
1972  } else {
1973  rc = writeFile(iosm, 1);
1974  }
1975  break;
1976  }
1977 
1978  if (iosm->goal != IOSM_PKGINSTALL)
1979  break;
1980 
1981  if (S_ISREG(st->st_mode) && iosm->lpath != NULL) {
1982  const char * opath = iosm->opath;
1983  char * t = (char *) xmalloc(strlen(iosm->lpath+1) + strlen(iosm->suffix) + 1);
1984  (void) stpcpy(t, iosm->lpath+1);
1985  iosm->opath = t;
1986  /* XXX link(iosm->opath, iosm->path) */
1987  rc = iosmNext(iosm, IOSM_LINK);
1988  if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) {
1989  *iosm->failedFile = xstrdup(iosm->path);
1990  }
1991  iosm->opath = _free(iosm->opath);
1992  iosm->opath = opath;
1993  break; /* XXX so that delayed hard links get skipped. */
1994  }
1995  if (S_ISREG(st->st_mode)) {
1996  const char * path = iosm->path;
1997  if (iosm->osuffix)
1998  iosm->path = iosmFsPath(iosm, st, NULL, NULL);
1999  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2000 
2001  if (rc == 0 && iosm->osuffix) {
2002  const char * opath = iosm->opath;
2003  iosm->opath = iosm->path;
2004  iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix);
2005  rc = iosmNext(iosm, IOSM_RENAME);
2006  if (!rc)
2008  _("%s saved as %s\n"),
2009  (iosm->opath ? iosm->opath : ""),
2010  (iosm->path ? iosm->path : ""));
2011  iosm->path = _free(iosm->path);
2012  iosm->opath = opath;
2013  }
2014 
2015  /*@-dependenttrans@*/
2016  iosm->path = path;
2017  /*@=dependenttrans@*/
2018  if (!(rc == IOSMERR_ENOENT)) return rc;
2019  rc = extractRegular(iosm);
2020  } else if (S_ISDIR(st->st_mode)) {
2021  mode_t st_mode = st->st_mode;
2022  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2023  if (rc == IOSMERR_ENOENT) {
2024  st->st_mode &= ~07777; /* XXX abuse st->st_mode */
2025  st->st_mode |= 00700;
2026  rc = iosmNext(iosm, IOSM_MKDIR);
2027  st->st_mode = st_mode; /* XXX restore st->st_mode */
2028  }
2029  } else if (S_ISLNK(st->st_mode)) {
2030 assert(iosm->lpath != NULL);
2031  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2032  if (rc == IOSMERR_ENOENT)
2033  rc = iosmNext(iosm, IOSM_SYMLINK);
2034  } else if (S_ISFIFO(st->st_mode)) {
2035  mode_t st_mode = st->st_mode;
2036  /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
2037  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2038  if (rc == IOSMERR_ENOENT) {
2039  st->st_mode = 0000; /* XXX abuse st->st_mode */
2040  rc = iosmNext(iosm, IOSM_MKFIFO);
2041  st->st_mode = st_mode; /* XXX restore st->st_mode */
2042  }
2043  } else if (S_ISCHR(st->st_mode) ||
2044  S_ISBLK(st->st_mode) ||
2045  /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
2046  {
2047  rc = iosmUNSAFE(iosm, IOSM_VERIFY);
2048  if (rc == IOSMERR_ENOENT)
2049  rc = iosmNext(iosm, IOSM_MKNOD);
2050  } else {
2051  /* XXX Repackaged payloads may be missing files. */
2052  if (iosm->repackaged)
2053  break;
2054 
2055  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2056  if (!IS_DEV_LOG(iosm->path))
2058  }
2059  if (S_ISREG(st->st_mode) && st->st_nlink > 1) {
2060  iosm->li->createdPath = iosm->li->linkIndex;
2061  rc = iosmMakeLinks(iosm);
2062  }
2063  break;
2064  case IOSM_POST:
2065  break;
2066  case IOSM_MKLINKS:
2067  rc = iosmMakeLinks(iosm);
2068  break;
2069  case IOSM_NOTIFY: /* XXX move from iosm to psm -> tsm */
2070 #if defined(_USE_RPMTS)
2071  if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) {
2072  rpmfi fi = iosmGetFi(iosm);
2073  rpmuint64_t archivePos = fdGetCpioPos(iosm->cfd);
2074  if (archivePos > fi->archivePos) {
2075  fi->archivePos = (unsigned long long) archivePos;
2076  (void) rpmtsNotify(iosmGetTs(iosm), fi->te,RPMCALLBACK_INST_PROGRESS,
2077  fi->archivePos, fi->archiveSize);
2078  }
2079  }
2080 #endif
2081  break;
2082  case IOSM_UNDO:
2083  if (iosm->postpone)
2084  break;
2085  if (iosm->goal == IOSM_PKGINSTALL) {
2086  /* XXX only erase if temp fn w suffix is in use */
2087  if (iosm->sufbuf[0] != '\0')
2088  (void) iosmNext(iosm,
2089  (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK));
2090 
2091 #ifdef NOTYET /* XXX remove only dirs just created, not all. */
2092  if (iosm->dnlx)
2093  (void) iosmNext(iosm, IOSM_RMDIRS);
2094 #endif
2095  errno = saveerrno;
2096  }
2097  if (iosm->failedFile && *iosm->failedFile == NULL)
2098  *iosm->failedFile = xstrdup(iosm->path);
2099  break;
2100  case IOSM_FINI:
2101  if (!iosm->postpone && iosm->commit) {
2102  if (iosm->goal == IOSM_PKGINSTALL)
2103  rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1)
2104  ? iosmCommitLinks(iosm) : iosmNext(iosm, IOSM_COMMIT));
2105  if (iosm->goal == IOSM_PKGCOMMIT)
2106  rc = iosmNext(iosm, IOSM_COMMIT);
2107  if (iosm->goal == IOSM_PKGERASE)
2108  rc = iosmNext(iosm, IOSM_COMMIT);
2109  }
2110  iosm->path = _free(iosm->path);
2111  iosm->lpath = _free(iosm->lpath);
2112  iosm->opath = _free(iosm->opath);
2113  memset(st, 0, sizeof(*st));
2114  memset(ost, 0, sizeof(*ost));
2115  break;
2116  case IOSM_COMMIT:
2117  /* Rename pre-existing modified or unmanaged file. */
2118  if (iosm->osuffix && iosm->diskchecked &&
2119  (iosm->exists || (iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))))
2120  {
2121  const char * opath = iosm->opath;
2122  const char * path = iosm->path;
2123  iosm->opath = iosmFsPath(iosm, st, NULL, NULL);
2124  iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix);
2125  rc = iosmNext(iosm, IOSM_RENAME);
2126  if (!rc) {
2127  rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"),
2128  (iosm->opath ? iosm->opath : ""),
2129  (iosm->path ? iosm->path : ""));
2130  }
2131  iosm->path = _free(iosm->path);
2132  iosm->path = path;
2133  iosm->opath = _free(iosm->opath);
2134  iosm->opath = opath;
2135  }
2136 
2137  /* Remove erased files. */
2138  if (iosm->goal == IOSM_PKGERASE) {
2139  if (iosm->action == FA_ERASE) {
2140  if (S_ISDIR(st->st_mode)) {
2141  rc = iosmNext(iosm, IOSM_RMDIR);
2142  if (!rc) break;
2143  switch (rc) {
2144  case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
2145  case IOSMERR_ENOTEMPTY:
2146  /* XXX make sure that build side permits %missingok on directories. */
2147  if (iosm->fflags & RPMFILE_MISSINGOK)
2148  /*@innerbreak@*/ break;
2149 
2150  /* XXX common error message. */
2151  rpmlog(
2153  _("rmdir of %s failed: Directory not empty\n"),
2154  iosm->path);
2155  /*@innerbreak@*/ break;
2156  default:
2157  rpmlog(
2158  (iosm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG),
2159  _("rmdir of %s failed: %s\n"),
2160  iosm->path, strerror(errno));
2161  /*@innerbreak@*/ break;
2162  }
2163  } else {
2164  rc = iosmNext(iosm, IOSM_UNLINK);
2165  if (!rc) break;
2166  switch (rc) {
2167  case IOSMERR_ENOENT:
2168  if (iosm->fflags & RPMFILE_MISSINGOK)
2169  /*@innerbreak@*/ break;
2170  /*@fallthrough@*/
2171  default:
2172  rpmlog(
2174  _("unlink of %s failed: %s\n"),
2175  iosm->path, strerror(errno));
2176  /*@innerbreak@*/ break;
2177  }
2178  }
2179  }
2180  /* XXX Failure to remove is not (yet) cause for failure. */
2181  if (!iosm->strict_erasures) rc = 0;
2182  break;
2183  }
2184 
2185  /* XXX Special case /dev/log, which shouldn't be packaged anyways */
2186  { rpmfi fi = (rpmfi) iosmGetFi(iosm);
2187  if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) {
2188  if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(iosm->path)) {
2189  /* Rename temporary to final file name. */
2190  if (!S_ISDIR(st->st_mode) &&
2191  (iosm->subdir || iosm->suffix || iosm->nsuffix))
2192  {
2193  iosm->opath = iosm->path;
2194  iosm->path = iosmFsPath(iosm, st, NULL, iosm->nsuffix);
2195  rc = iosmNext(iosm, IOSM_RENAME);
2196  if (rc)
2197  (void) Unlink(iosm->opath);
2198  else if (iosm->nsuffix) {
2199  const char * opath = iosmFsPath(iosm, st, NULL, NULL);
2200  rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
2201  (opath ? opath : ""),
2202  (iosm->path ? iosm->path : ""));
2203  opath = _free(opath);
2204  }
2205  iosm->opath = _free(iosm->opath);
2206  }
2207  /*
2208  * Set file security context (if not disabled).
2209  */
2210  if (!rc && !getuid()) {
2211  rc = iosmMapFContext(iosm);
2212  if (!rc)
2213  rc = iosmNext(iosm, IOSM_LSETFCON);
2214  iosm->fcontext = NULL;
2215  }
2216  if (S_ISLNK(st->st_mode)) {
2217  if (!rc && !getuid())
2218  rc = iosmNext(iosm, IOSM_LCHOWN);
2219  } else {
2220  if (!rc && !getuid())
2221  rc = iosmNext(iosm, IOSM_CHOWN);
2222  if (!rc)
2223  rc = iosmNext(iosm, IOSM_CHMOD);
2224  if (!rc) {
2225  time_t mtime = st->st_mtime;
2226  if (fi->fmtimes)
2227  st->st_mtime = fi->fmtimes[iosm->ix];
2228  rc = iosmNext(iosm, IOSM_UTIME);
2229  st->st_mtime = mtime;
2230  }
2231  }
2232  }
2233  }
2234  }
2235 
2236  /* Notify on success. */
2237  if (!rc) rc = iosmNext(iosm, IOSM_NOTIFY);
2238  else if (iosm->failedFile && *iosm->failedFile == NULL) {
2239  *iosm->failedFile = iosm->path;
2240  iosm->path = NULL;
2241  }
2242  break;
2243  case IOSM_DESTROY:
2244  iosm->path = _free(iosm->path);
2245 
2246  /* Check for hard links missing from payload. */
2247  while ((iosm->li = iosm->links) != NULL) {
2248  iosm->links = iosm->li->next;
2249  iosm->li->next = NULL;
2250  if (iosm->goal == IOSM_PKGINSTALL &&
2251  iosm->commit && iosm->li->linksLeft)
2252  {
2253  for (i = 0 ; i < iosm->li->linksLeft; i++) {
2254  if (iosm->li->filex[i] < 0)
2255  /*@innercontinue@*/ continue;
2257  if (iosm->failedFile && *iosm->failedFile == NULL) {
2258  iosm->ix = iosm->li->filex[i];
2259  if (!iosmNext(iosm, IOSM_MAP)) {
2260  *iosm->failedFile = iosm->path;
2261  iosm->path = NULL;
2262  }
2263  }
2264  /*@loopbreak@*/ break;
2265  }
2266  }
2267  if (iosm->goal == IOSM_PKGBUILD &&
2268  (iosm->mapFlags & IOSM_ALL_HARDLINKS))
2269  {
2271  }
2272  freeHardLink(iosm->li); iosm->li = NULL;
2273  }
2274  iosm->ldn = _free(iosm->ldn);
2275  iosm->ldnalloc = iosm->ldnlen = 0;
2276  iosm->rdbuf = iosm->rdb = _free(iosm->rdb);
2277  iosm->wrbuf = iosm->wrb = _free(iosm->wrb);
2278  break;
2279  case IOSM_VERIFY:
2280  if (iosm->diskchecked && !iosm->exists) {
2281  rc = IOSMERR_ENOENT;
2282  break;
2283  }
2284  if (S_ISREG(st->st_mode)) {
2285  char * path = (char *) alloca(strlen(iosm->path) + sizeof("-RPMDELETE"));
2286  (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE");
2287  /*
2288  * XXX HP-UX (and other os'es) don't permit unlink on busy
2289  * XXX files.
2290  */
2291  iosm->opath = iosm->path;
2292  iosm->path = path;
2293  rc = iosmNext(iosm, IOSM_RENAME);
2294  if (!rc)
2295  (void) iosmNext(iosm, IOSM_UNLINK);
2296  else
2297  rc = IOSMERR_UNLINK_FAILED;
2298  iosm->path = iosm->opath;
2299  iosm->opath = NULL;
2300  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2301  /*@notreached@*/ break;
2302  } else if (S_ISDIR(st->st_mode)) {
2303  if (S_ISDIR(ost->st_mode)) return 0;
2304  if (S_ISLNK(ost->st_mode)) {
2305  rc = iosmUNSAFE(iosm, IOSM_STAT);
2306  if (rc == IOSMERR_ENOENT) rc = 0;
2307  if (rc) break;
2308  errno = saveerrno;
2309  if (S_ISDIR(ost->st_mode)) return 0;
2310  }
2311  } else if (S_ISLNK(st->st_mode)) {
2312  if (S_ISLNK(ost->st_mode)) {
2313  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
2314  rc = iosmUNSAFE(iosm, IOSM_READLINK);
2315  errno = saveerrno;
2316  if (rc) break;
2317  if (!strcmp(iosm->lpath, iosm->rdbuf)) return 0;
2318  }
2319  } else if (S_ISFIFO(st->st_mode)) {
2320  if (S_ISFIFO(ost->st_mode)) return 0;
2321  } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
2322  if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
2323  (ost->st_rdev == st->st_rdev)) return 0;
2324  } else if (S_ISSOCK(st->st_mode)) {
2325  if (S_ISSOCK(ost->st_mode)) return 0;
2326  }
2327  /* XXX shouldn't do this with commit/undo. */
2328  rc = 0;
2329  if (iosm->stage == IOSM_PROCESS) rc = iosmNext(iosm, IOSM_UNLINK);
2330  if (rc == 0) rc = IOSMERR_ENOENT;
2331  return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */
2332  /*@notreached@*/ break;
2333 
2334  case IOSM_UNLINK:
2335  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2336  if (iosm->mapFlags & IOSM_SBIT_CHECK) {
2337  struct stat stb;
2338  if (Lstat(iosm->path, &stb) == 0
2339  && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0)
2340  {
2341  /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */
2342  (void)Chmod(iosm->path, stb.st_mode & 0777);
2343  }
2344  }
2345  rc = Unlink(iosm->path);
2346  if (iosm->debug && (stage & IOSM_SYSCALL))
2347  rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur,
2348  iosm->path, (rc < 0 ? strerror(errno) : ""));
2349  if (rc < 0)
2350  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_UNLINK_FAILED);
2351  break;
2352  case IOSM_RENAME:
2353  /* XXX Remove setuid/setgid bits on possibly hard linked files. */
2354  if (iosm->mapFlags & IOSM_SBIT_CHECK) {
2355  struct stat stb;
2356  if (Lstat(iosm->path, &stb) == 0
2357  && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0)
2358  {
2359  /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */
2360  (void)Chmod(iosm->path, stb.st_mode & 0777);
2361  }
2362  }
2363  rc = Rename(iosm->opath, iosm->path);
2364  /* XXX Repackaged payloads may be missing files. */
2365  if (iosm->repackaged)
2366  rc = 0;
2367 #if defined(ETXTBSY)
2368  if (rc && errno == ETXTBSY) {
2369  char * path = (char *) alloca(strlen(iosm->path) + sizeof("-RPMDELETE"));
2370  (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE");
2371  /*
2372  * XXX HP-UX (and other os'es) don't permit rename to busy
2373  * XXX files.
2374  */
2375  rc = Rename(iosm->path, path);
2376  if (!rc) rc = Rename(iosm->opath, iosm->path);
2377  }
2378 #endif
2379  if (iosm->debug && (stage & IOSM_SYSCALL))
2380  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2381  iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2382  if (rc < 0) rc = IOSMERR_RENAME_FAILED;
2383  break;
2384  case IOSM_MKDIR:
2385  rc = Mkdir(iosm->path, (st->st_mode & 07777));
2386  if (iosm->debug && (stage & IOSM_SYSCALL))
2387  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2388  iosm->path, (unsigned)(st->st_mode & 07777),
2389  (rc < 0 ? strerror(errno) : ""));
2390  if (rc < 0) rc = IOSMERR_MKDIR_FAILED;
2391  break;
2392  case IOSM_RMDIR:
2393  rc = Rmdir(iosm->path);
2394  if (iosm->debug && (stage & IOSM_SYSCALL))
2395  rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur,
2396  iosm->path, (rc < 0 ? strerror(errno) : ""));
2397  if (rc < 0)
2398  switch (errno) {
2399  case ENOENT: rc = IOSMERR_ENOENT; /*@switchbreak@*/ break;
2400  case ENOTEMPTY: rc = IOSMERR_ENOTEMPTY; /*@switchbreak@*/ break;
2401  default: rc = IOSMERR_RMDIR_FAILED; /*@switchbreak@*/ break;
2402  }
2403  break;
2404  case IOSM_LSETFCON:
2405  { const char * iosmpath = NULL;
2406  if (iosm->fcontext == NULL || *iosm->fcontext == '\0'
2407  || !strcmp(iosm->fcontext, "<<none>>"))
2408  break;
2409  (void) urlPath(iosm->path, &iosmpath); /* XXX iosm->path */
2410  rc = rpmsxLsetfilecon(NULL, iosmpath, 0, iosm->fcontext);
2411  if (iosm->debug && (stage & IOSM_SYSCALL))
2412  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2413  iosm->path, iosm->fcontext,
2414  (rc < 0 ? strerror(errno) : ""));
2415  if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : IOSMERR_LSETFCON_FAILED);
2416  } break;
2417  case IOSM_CHOWN:
2418  rc = Chown(iosm->path, st->st_uid, st->st_gid);
2419  if (iosm->debug && (stage & IOSM_SYSCALL))
2420  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2421  iosm->path, (int)st->st_uid, (int)st->st_gid,
2422  (rc < 0 ? strerror(errno) : ""));
2423  if (rc < 0) rc = IOSMERR_CHOWN_FAILED;
2424  break;
2425  case IOSM_LCHOWN:
2426 #if ! CHOWN_FOLLOWS_SYMLINK
2427  rc = Lchown(iosm->path, st->st_uid, st->st_gid);
2428  if (iosm->debug && (stage & IOSM_SYSCALL))
2429  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
2430  iosm->path, (int)st->st_uid, (int)st->st_gid,
2431  (rc < 0 ? strerror(errno) : ""));
2432  if (rc < 0) rc = IOSMERR_CHOWN_FAILED;
2433 #endif
2434  break;
2435  case IOSM_CHMOD:
2436  rc = Chmod(iosm->path, (st->st_mode & 07777));
2437  if (iosm->debug && (stage & IOSM_SYSCALL))
2438  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2439  iosm->path, (unsigned)(st->st_mode & 07777),
2440  (rc < 0 ? strerror(errno) : ""));
2441  if (rc < 0) rc = IOSMERR_CHMOD_FAILED;
2442  break;
2443  case IOSM_UTIME:
2444  { struct utimbuf stamp;
2445  stamp.actime = st->st_mtime;
2446  stamp.modtime = st->st_mtime;
2447  rc = Utime(iosm->path, &stamp);
2448  if (iosm->debug && (stage & IOSM_SYSCALL))
2449  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0x%x) %s\n", cur,
2450  iosm->path, (unsigned)st->st_mtime,
2451  (rc < 0 ? strerror(errno) : ""));
2452  if (rc < 0) rc = IOSMERR_UTIME_FAILED;
2453  }
2454  break;
2455  case IOSM_SYMLINK:
2456  rc = Symlink(iosm->lpath, iosm->path);
2457  if (iosm->debug && (stage & IOSM_SYSCALL))
2458  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2459  iosm->lpath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2460  if (rc < 0) rc = IOSMERR_SYMLINK_FAILED;
2461  break;
2462  case IOSM_LINK:
2463  rc = Link(iosm->opath, iosm->path);
2464  if (iosm->debug && (stage & IOSM_SYSCALL))
2465  rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur,
2466  iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : ""));
2467  if (rc < 0) rc = IOSMERR_LINK_FAILED;
2468  break;
2469  case IOSM_MKFIFO:
2470  rc = Mkfifo(iosm->path, (st->st_mode & 07777));
2471  if (iosm->debug && (stage & IOSM_SYSCALL))
2472  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
2473  iosm->path, (unsigned)(st->st_mode & 07777),
2474  (rc < 0 ? strerror(errno) : ""));
2475  if (rc < 0) rc = IOSMERR_MKFIFO_FAILED;
2476  break;
2477  case IOSM_MKNOD:
2478  /*@-unrecog -portability @*/ /* FIX: check S_IFIFO or dev != 0 */
2479  rc = Mknod(iosm->path, (st->st_mode & ~07777), st->st_rdev);
2480  /*@=unrecog =portability @*/
2481  if (iosm->debug && (stage & IOSM_SYSCALL))
2482  rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur,
2483  iosm->path, (unsigned)(st->st_mode & ~07777),
2484  (unsigned)st->st_rdev,
2485  (rc < 0 ? strerror(errno) : ""));
2486  if (rc < 0) rc = IOSMERR_MKNOD_FAILED;
2487  break;
2488  case IOSM_LSTAT:
2489  rc = Lstat(iosm->path, ost);
2490  if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT)
2491  rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur,
2492  iosm->path, (rc < 0 ? strerror(errno) : ""));
2493  if (rc < 0) {
2494  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_LSTAT_FAILED);
2495  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2496  }
2497  break;
2498  case IOSM_STAT:
2499  rc = Stat(iosm->path, ost);
2500  if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT)
2501  rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur,
2502  iosm->path, (rc < 0 ? strerror(errno) : ""));
2503  if (rc < 0) {
2504  rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_STAT_FAILED);
2505  memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */
2506  }
2507  break;
2508  case IOSM_READLINK:
2509  /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */
2510  rc = Readlink(iosm->path, iosm->rdbuf, iosm->rdsize - 1);
2511  if (iosm->debug && (stage & IOSM_SYSCALL))
2512  rpmlog(RPMLOG_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur,
2513  iosm->path, (int)(iosm->rdsize -1), (rc < 0 ? strerror(errno) : ""));
2514  if (rc < 0) rc = IOSMERR_READLINK_FAILED;
2515  else {
2516  iosm->rdnb = rc;
2517  iosm->rdbuf[iosm->rdnb] = '\0';
2518  rc = 0;
2519  }
2520  break;
2521  case IOSM_CHROOT:
2522  break;
2523 
2524  case IOSM_NEXT:
2525  rc = iosmUNSAFE(iosm, IOSM_HREAD);
2526  if (rc) break;
2527  if (!strcmp(iosm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */
2528  iosm->path = _free(iosm->path);
2529  rc = IOSMERR_HDR_TRAILER;
2530  }
2531  if (!rc)
2532  rc = iosmNext(iosm, IOSM_POS);
2533  break;
2534  case IOSM_EAT:
2535  for (left = st->st_size; left > 0; left -= iosm->rdnb) {
2536  iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left);
2537  rc = iosmNext(iosm, IOSM_DREAD);
2538  if (rc)
2539  /*@loopbreak@*/ break;
2540  }
2541  break;
2542  case IOSM_POS:
2543  left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize;
2544  if (left) {
2545  iosm->wrlen = left;
2546  (void) iosmNext(iosm, IOSM_DREAD);
2547  }
2548  break;
2549  case IOSM_PAD:
2550  left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize;
2551  if (left) {
2552  if (iosm->blksize == 2)
2553  iosm->rdbuf[0] = '\n'; /* XXX ar(1) pads with '\n' */
2554  else
2555  memset(iosm->rdbuf, 0, left);
2556  /* XXX DWRITE uses rdnb for I/O length. */
2557  iosm->rdnb = left;
2558  (void) iosmNext(iosm, IOSM_DWRITE);
2559  }
2560  break;
2561  case IOSM_TRAILER:
2562  rc = (*iosm->trailerWrite) (iosm); /* Write payload trailer. */
2563  break;
2564  case IOSM_HREAD:
2565  rc = iosmNext(iosm, IOSM_POS);
2566  if (!rc)
2567  rc = (*iosm->headerRead) (iosm, st);/* Read next payload header. */
2568  break;
2569  case IOSM_HWRITE:
2570  rc = (*iosm->headerWrite) (iosm, st); /* Write next payload header. */
2571  break;
2572  case IOSM_DREAD:
2573  iosm->rdnb = Fread(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->wrlen, iosm->cfd);
2574  if (iosm->debug && (stage & IOSM_SYSCALL))
2575  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n",
2576  cur, (iosm->wrbuf == iosm->wrb ? "wrbuf" : "mmap"),
2577  (int)iosm->wrlen, (int)iosm->rdnb);
2578  if (iosm->rdnb != iosm->wrlen || Ferror(iosm->cfd))
2579  rc = IOSMERR_READ_FAILED;
2580  if (iosm->rdnb > 0)
2581  fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->rdnb);
2582  break;
2583  case IOSM_DWRITE:
2584  iosm->wrnb = Fwrite(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdnb, iosm->cfd);
2585  if (iosm->debug && (stage & IOSM_SYSCALL))
2586  rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n",
2587  cur, (iosm->rdbuf == iosm->rdb ? "rdbuf" : "mmap"),
2588  (int)iosm->rdnb, (int)iosm->wrnb);
2589  if (iosm->rdnb != iosm->wrnb || Ferror(iosm->cfd))
2590  rc = IOSMERR_WRITE_FAILED;
2591  if (iosm->wrnb > 0)
2592  fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->wrnb);
2593  break;
2594 
2595  case IOSM_ROPEN:
2596  iosm->rfd = Fopen(iosm->path, "r.fdio");
2597  if (iosm->rfd == NULL || Ferror(iosm->rfd)) {
2598  if (iosm->rfd != NULL) (void) iosmNext(iosm, IOSM_RCLOSE);
2599  iosm->rfd = NULL;
2600  rc = IOSMERR_OPEN_FAILED;
2601  break;
2602  }
2603 #if defined(POSIX_FADV_WILLNEED)
2604  (void) Fadvise(iosm->rfd, 0, 0, POSIX_FADV_WILLNEED);
2605 #endif
2606  if (iosm->debug && (stage & IOSM_SYSCALL))
2607  rpmlog(RPMLOG_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur,
2608  iosm->path, iosm->rfd, iosm->rdbuf);
2609  break;
2610  case IOSM_READ:
2611  iosm->rdnb = Fread(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdlen, iosm->rfd);
2612  if (iosm->debug && (stage & IOSM_SYSCALL))
2613  rpmlog(RPMLOG_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n",
2614  cur, (int)iosm->rdlen, (int)iosm->rdnb);
2615  if (iosm->rdnb != iosm->rdlen || Ferror(iosm->rfd))
2616  rc = IOSMERR_READ_FAILED;
2617  break;
2618  case IOSM_RCLOSE:
2619  if (iosm->rfd != NULL) {
2620  if (iosm->debug && (stage & IOSM_SYSCALL))
2621  rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->rfd);
2622  (void) rpmswAdd(&iosm->op_digest,
2623  fdstat_op(iosm->rfd, FDSTAT_DIGEST));
2624  (void) Fclose(iosm->rfd);
2625  errno = saveerrno;
2626  }
2627  iosm->rfd = NULL;
2628  break;
2629  case IOSM_WOPEN:
2630  iosm->wfd = Fopen(iosm->path, "w.fdio");
2631  if (iosm->wfd == NULL || Ferror(iosm->wfd)) {
2632  if (iosm->wfd != NULL) (void) iosmNext(iosm, IOSM_WCLOSE);
2633  iosm->wfd = NULL;
2634  rc = IOSMERR_OPEN_FAILED;
2635  }
2636 #if defined(POSIX_FADV_DONTNEED)
2637  else
2638  (void) Fadvise(iosm->wfd, 0, 0, POSIX_FADV_DONTNEED);
2639 #endif
2640  if (iosm->debug && (stage & IOSM_SYSCALL))
2641  rpmlog(RPMLOG_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur,
2642  iosm->path, iosm->wfd, iosm->wrbuf);
2643  break;
2644  case IOSM_WRITE:
2645  iosm->wrnb = Fwrite(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->rdnb, iosm->wfd);
2646  if (iosm->debug && (stage & IOSM_SYSCALL))
2647  rpmlog(RPMLOG_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n",
2648  cur, (int)iosm->rdnb, (int)iosm->wrnb);
2649  if (iosm->rdnb != iosm->wrnb || Ferror(iosm->wfd))
2650  rc = IOSMERR_WRITE_FAILED;
2651  break;
2652  case IOSM_WCLOSE:
2653  if (iosm->wfd != NULL) {
2654  if (iosm->debug && (stage & IOSM_SYSCALL))
2655  rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->wfd);
2656  (void) rpmswAdd(&iosm->op_digest,
2657  fdstat_op(iosm->wfd, FDSTAT_DIGEST));
2658  (void) Fclose(iosm->wfd);
2659  errno = saveerrno;
2660  }
2661  iosm->wfd = NULL;
2662  break;
2663 
2664  default:
2665  break;
2666  }
2667 
2668  if (!(stage & IOSM_INTERNAL)) {
2669  iosm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc);
2670  }
2671  return rc;
2672 }
2673 /*@=compmempass@*/
2674 
2675 #define IOSM_SKIPPING(_a) \
2676  ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPCOLOR)
2677 
2679 {
2680  return IOSM_SKIPPING(action);
2681 }
2682 
2683 /*@observer@*/ const char * iosmFileActionString(iosmFileAction a)
2684 {
2685  switch (a) {
2686  case FA_UNKNOWN: return "unknown";
2687  case FA_CREATE: return "create";
2688  case FA_COPYOUT: return "copyout";
2689  case FA_COPYIN: return "copyin";
2690  case FA_BACKUP: return "backup";
2691  case FA_SAVE: return "save";
2692  case FA_SKIP: return "skip";
2693  case FA_ALTNAME: return "altname";
2694  case FA_ERASE: return "erase";
2695  case FA_SKIPNSTATE: return "skipnstate";
2696  case FA_SKIPNETSHARED: return "skipnetshared";
2697  case FA_SKIPCOLOR: return "skipcolor";
2698  default: return "???";
2699  }
2700  /*@notreached@*/
2701 }
2702 
2703 /*@observer@*/ const char * iosmFileStageString(iosmFileStage a) {
2704  switch(a) {
2705  case IOSM_UNKNOWN: return "unknown";
2706 
2707  case IOSM_PKGINSTALL:return "INSTALL";
2708  case IOSM_PKGERASE: return "ERASE";
2709  case IOSM_PKGBUILD: return "BUILD";
2710  case IOSM_PKGCOMMIT: return "COMMIT";
2711  case IOSM_PKGUNDO: return "UNDO";
2712 
2713  case IOSM_CREATE: return "create";
2714  case IOSM_INIT: return "init";
2715  case IOSM_MAP: return "map";
2716  case IOSM_MKDIRS: return "mkdirs";
2717  case IOSM_RMDIRS: return "rmdirs";
2718  case IOSM_PRE: return "pre";
2719  case IOSM_PROCESS: return "process";
2720  case IOSM_POST: return "post";
2721  case IOSM_MKLINKS: return "mklinks";
2722  case IOSM_NOTIFY: return "notify";
2723  case IOSM_UNDO: return "undo";
2724  case IOSM_FINI: return "fini";
2725  case IOSM_COMMIT: return "commit";
2726  case IOSM_DESTROY: return "destroy";
2727  case IOSM_VERIFY: return "verify";
2728 
2729  case IOSM_UNLINK: return "Unlink";
2730  case IOSM_RENAME: return "Rename";
2731  case IOSM_MKDIR: return "Mkdir";
2732  case IOSM_RMDIR: return "Rmdir";
2733  case IOSM_LSETFCON: return "lsetfcon";
2734  case IOSM_CHOWN: return "Chown";
2735  case IOSM_LCHOWN: return "Lchown";
2736  case IOSM_CHMOD: return "Chmod";
2737  case IOSM_UTIME: return "Utime";
2738  case IOSM_SYMLINK: return "Symlink";
2739  case IOSM_LINK: return "Link";
2740  case IOSM_MKFIFO: return "Mkfifo";
2741  case IOSM_MKNOD: return "Mknod";
2742  case IOSM_LSTAT: return "Lstat";
2743  case IOSM_STAT: return "Stat";
2744  case IOSM_READLINK: return "Readlink";
2745  case IOSM_CHROOT: return "Chroot";
2746 
2747  case IOSM_NEXT: return "next";
2748  case IOSM_EAT: return "eat";
2749  case IOSM_POS: return "pos";
2750  case IOSM_PAD: return "pad";
2751  case IOSM_TRAILER: return "trailer";
2752  case IOSM_HREAD: return "hread";
2753  case IOSM_HWRITE: return "hwrite";
2754  case IOSM_DREAD: return "Fread";
2755  case IOSM_DWRITE: return "Fwrite";
2756 
2757  case IOSM_ROPEN: return "Fopen";
2758  case IOSM_READ: return "Fread";
2759  case IOSM_RCLOSE: return "Fclose";
2760  case IOSM_WOPEN: return "Fopen";
2761  case IOSM_WRITE: return "Fwrite";
2762  case IOSM_WCLOSE: return "Fclose";
2763 
2764  default: return "???";
2765  }
2766  /*@noteached@*/
2767 }
2768 
2769 char * iosmStrerror(int rc)
2770 {
2771  char msg[256];
2772  const char *s;
2773  int l, myerrno = errno;
2774 
2775  strcpy(msg, "cpio: ");
2776  switch (rc) {
2777  default:
2778  s = msg + strlen(msg);
2779  sprintf((char *)s, _("(error 0x%x)"), (unsigned)rc);
2780  s = NULL;
2781  break;
2782  case IOSMERR_BAD_MAGIC: s = _("Bad magic"); break;
2783  case IOSMERR_BAD_HEADER: s = _("Bad/unreadable header"); break;
2784 
2785  case IOSMERR_OPEN_FAILED: s = "open"; break;
2786  case IOSMERR_CHMOD_FAILED: s = "chmod"; break;
2787  case IOSMERR_CHOWN_FAILED: s = "chown"; break;
2788  case IOSMERR_WRITE_FAILED: s = "write"; break;
2789  case IOSMERR_UTIME_FAILED: s = "utime"; break;
2790  case IOSMERR_UNLINK_FAILED: s = "unlink"; break;
2791  case IOSMERR_RENAME_FAILED: s = "rename"; break;
2792  case IOSMERR_SYMLINK_FAILED: s = "symlink"; break;
2793  case IOSMERR_STAT_FAILED: s = "stat"; break;
2794  case IOSMERR_LSTAT_FAILED: s = "lstat"; break;
2795  case IOSMERR_MKDIR_FAILED: s = "mkdir"; break;
2796  case IOSMERR_RMDIR_FAILED: s = "rmdir"; break;
2797  case IOSMERR_MKNOD_FAILED: s = "mknod"; break;
2798  case IOSMERR_MKFIFO_FAILED: s = "mkfifo"; break;
2799  case IOSMERR_LINK_FAILED: s = "link"; break;
2800  case IOSMERR_READLINK_FAILED: s = "readlink"; break;
2801  case IOSMERR_READ_FAILED: s = "read"; break;
2802  case IOSMERR_COPY_FAILED: s = "copy"; break;
2803  case IOSMERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
2804 
2805  case IOSMERR_HDR_SIZE: s = _("Header size too big"); break;
2806  case IOSMERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
2807  case IOSMERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
2808  case IOSMERR_DIGEST_MISMATCH: s = _("File digest mismatch"); break;
2809  case IOSMERR_INTERNAL: s = _("Internal error"); break;
2810  case IOSMERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
2811  case IOSMERR_ENOENT: s = strerror(ENOENT); break;
2812  case IOSMERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
2813  }
2814 
2815  l = sizeof(msg) - strlen(msg) - 1;
2816  if (s != NULL) {
2817  if (l > 0) strncat(msg, s, l);
2818  l -= strlen(s);
2819  }
2820  if ((rc & IOSMERR_CHECK_ERRNO) && myerrno) {
2821  s = _(" failed - ");
2822  if (l > 0) strncat(msg, s, l);
2823  l -= strlen(s);
2824  if (l > 0) strncat(msg, strerror(myerrno), l);
2825  }
2826  return xstrdup(msg);
2827 }
int arHeaderRead(void *_iosm, struct stat *st)
Read ar(1) header.
Definition: ar.c:92
const bson * b
Definition: bson.h:280
static const char * suffix[]
Definition: rpmgrep.c:188
Definition: iosm.h:34
struct hardLink_s * li
Definition: iosm.h:250
char * ldn
Definition: iosm.h:269
iosmMapFlags cpioMapFlags
Definition: iosm.c:29
static int dnlCount(const DNLI_t dnli)
Definition: iosm.c:306
int tarTrailerWrite(void *_iosm)
Write cpio trailer to payload.
Definition: tar.c:499
struct stat sb
Definition: iosm.h:305
void * rpmtsNotify(rpmts ts, rpmte te, rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total)
Perform transaction progress notify callback.
Definition: rpmts.c:1281
#define _fafilter(_a)
const char * nsuffix
Definition: iosm.h:262
const char ** failedFile
Definition: iosm.h:254
const char bson_timestamp_t * ts
Definition: bson.h:1004
int postpone
Definition: iosm.h:272
#define IOSM_VERBOSE
Definition: iosm.h:105
int rpmsxLsetfilecon(rpmsx sx, const char *fn, mode_t mode, const char *scon)
Definition: rpmsx.c:248
static const char * dnlNextIterator(DNLI_t dnli)
Return next directory name (from file info).
Definition: iosm.c:426
enum iosmFileAction_e iosmFileAction
File disposition(s) during package install/erase processing.
static int saveHardLink(IOSM_t iosm)
Save hard link in chain.
Definition: iosm.c:478
int Symlink(const char *oldpath, const char *newpath)
symlink(3) clone.
Definition: rpmrpc.c:2120
Structures used for an "rpmte" transaction element.
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
fwrite(3) clone.
Definition: rpmio.c:2434
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:2833
static int iosmMkdirs(IOSM_t iosm)
Create (if necessary) directories not explicitly included in package.
Definition: iosm.c:1475
const char * lpath
Definition: iosm.h:222
Definition: iosm.h:159
static int iosmMapFContext(IOSM_t iosm)
Definition: iosm.c:835
Definition: iosm.h:131
static void * dnlInitIterator(const IOSM_t iosm, int reverse)
Create directory name iterator.
Definition: iosm.c:328
iosmFileAction action
Definition: iosm.h:301
const char int time
Definition: bson.h:1005
enum pgpHashAlgo_e pgpHashAlgo
9.4.
char * wrb
Definition: iosm.h:240
const char * path
Definition: iosm.h:220
rpmfi rpmfiUnlink(rpmfi fi, const char *msg)
Unreference a file info set instance.
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
void * rpmsqThread(void *(*start)(void *arg), void *arg)
Call a function in a thread.
Definition: rpmsq.c:656
const char * dirName
Definition: iosm.h:290
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
rpmuint32_t digestlen
Definition: iosm.h:288
FD_t fdLink(void *cookie, const char *msg)
Definition: rpmdb.c:436
#define reverse(bot, top)
Definition: merge.c:102
#define S_ISLNK(mode)
Definition: system.h:651
static int mapFind(IOSMI_t iter, const char *iosmPath)
Locate archive path in file info.
Definition: iosm.c:247
size_t wrsize
Definition: iosm.h:241
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2916
int repackaged
Definition: iosm.h:279
size_t lmtaboff
Definition: iosm.h:319
int errno
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.
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
Retrieve operation timestamp from a transaction set.
Definition: pkgio.c:133
int adding
Definition: iosm.h:282
IOSMI_t iter
Definition: iosm.h:245
int Fadvise(FD_t fd, off_t offset, off_t length, int advice)
posix_fadvise(2) clone.
Definition: rpmrpc.c:1495
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
static int mapNextIterator(void *_iter)
Return next index into file info.
Definition: iosm.c:194
rpmElementType rpmteType(rpmte te)
Retrieve type of transaction element.
Definition: rpmte.c:311
int iosmMapPath(IOSM_t iosm)
Map next file path and action.
Definition: iosm.c:858
rpmts rpmtsLink(rpmts ts, const char *msg)
Reference a transaction set instance.
int ix
Definition: iosm.h:246
#define S_ISSOCK(mode)
Definition: system.h:655
enum iosmFileStage_e iosmFileStage
const char * rpmfiBN(rpmfi fi)
Return current base name from file info set.
Definition: rpmfi.c:141
const unsigned char * digest
Definition: iosm.h:296
struct rpmop_s op_digest
Definition: iosm.h:321
IOSM_t freeIOSM(IOSM_t iosm)
Destroy I/O state machine instance.
Definition: iosm.c:580
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
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
static void * freeHardLink(struct hardLink_s *li)
Destroy set of hard links.
Definition: iosm.c:564
Structures used for cpio(1) archives.
Definition: iosm.h:30
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
const char * subdir
Definition: iosm.h:256
Definition: iosm.h:118
static rpmop fdstat_op(FD_t fd, fdOpX opx)
int(* headerWrite)(void *_iosm, struct stat *st)
Definition: iosm.h:311
size_t wrnb
Definition: iosm.h:243
int fsync
Definition: mongo.h:439
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
int i
Definition: fsm.c:274
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct rpmds_s * rpmds
Definition: iosm.c:34
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
FD_t wfd
Definition: iosm.h:236
struct dnli_s * DNLI_t
Directory name iterator.
char * lmtab
Definition: iosm.h:317
size_t rdnb
Definition: iosm.h:235
Directory name iterator.
Definition: fsm.c:268
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
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
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
char sufbuf[64]
Definition: iosm.h:265
#define IS_DEV_LOG(_x)
Definition: iosm.c:1631
int gnameToGid(const char *thisGname, gid_t *gid)
Definition: ugid.c:71
FD_t fdFree(FD_t fd, const char *msg)
const char * fdigest
Definition: iosm.h:294
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
int Rename(const char *oldpath, const char *newpath)
rename(2) clone.
Definition: rpmrpc.c:286
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
void * fi
Definition: iosm.h:209
struct iosm_s * IOSM_t
File state machine data.
Definition: iosm.h:17
#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
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:2678
Structures used for tar(1) archives.
Definition: iosm.h:160
struct rpmPRCO_s * rpmPRCO
Definition: iosm.c:49
const char * fcontext
Definition: iosm.h:298
static int writeFile(IOSM_t iosm, int writeData)
Write next item to payload stream.
Definition: iosm.c:1102
int(* trailerWrite)(void *_iosm)
Definition: iosm.h:313
static void * dnlFreeIterator(const void *_dnli)
Destroy directory name iterator.
Definition: iosm.c:294
#define IOSM_SYSCALL
Definition: iosm.h:107
#define IOSM_DEAD
Definition: iosm.h:108
static void * mapFreeIterator(void *_iter)
Destroy file info iterator.
Definition: iosm.c:150
#define SUFFIX_RPMSAVE
Definition: iosm.c:106
The FD_t File Handle data structure.
static void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo, void *datap, size_t *lenp, int asAscii)
int rc
Definition: iosm.h:277
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
static unsigned long long fdGetCpioPos(FD_t fd)
#define _tsmask
int Mknod(const char *path, mode_t mode, dev_t dev)
mknod(3) clone.
Definition: rpmrpc.c:1989
void * alKey
An added/available package retrieval key.
Definition: rpmtypes.h:19
char * rdb
Definition: iosm.h:232
struct rpmRelocation_s * rpmRelocation
Definition: iosm.c:35
static void * mapInitIterator(rpmfi fi, int reverse)
Create file info iterator.
Definition: iosm.c:171
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
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:1638
void * iosmGetFi(const IOSM_t iosm)
Retrieve transaction element file info from I/O state machine iterator.
Definition: iosm.c:97
static int iosmStrCmp(const void *a, const void *b)
Definition: iosm.c:213
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:2534
int nofcontexts
Definition: iosm.h:285
char * iosmStrerror(int rc)
Return formatted error message on payload handling failure.
Definition: iosm.c:2769
rpmfi fi
Definition: fsm.c:269
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
spectags st
Definition: rpmspec.h:125
#define IOSM_SKIPPING(_a)
Definition: iosm.c:2675
int isave
Definition: fsm.c:273
iosmFileStage nstage
Definition: iosm.h:304
char * wrbuf
Definition: iosm.h:238
struct rpmts_s * rpmts
Definition: iosm.c:18
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
static void fdSetCpioPos(FD_t fd, long int cpioPos)
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
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
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
enum iosmMapFlags_e iosmMapFlags
Definition: rpmte.h:37
const char const int i
Definition: bson.h:778
struct rpmte_s * rpmte
Definition: iosm.c:19
void * iosmGetTs(const IOSM_t iosm)
Retrieve transaction set from I/O state machine iterator.
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int iosmCommitLinks(IOSM_t iosm)
Commit hard linked file set atomically.
Definition: iosm.c:1375
rpmfi rpmfiLink(rpmfi fi, const char *msg)
Reference a file info set instance.
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
Definition: iosm.h:29
int isave
Definition: iosm.h:211
Definition: iosm.h:161
#define CPIO_TRAILER
Definition: cpio.h:16
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
size_t lmtablen
Definition: iosm.h:318
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
int reverse
Definition: fsm.c:272
FD_t rfd
Definition: iosm.h:228
int nofdigests
Definition: iosm.h:284
const char * iosmFileStageString(iosmFileStage a)
Return formatted string representation of file stages.
Definition: iosm.c:2703
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
struct hardLink_s * links
Definition: iosm.h:248
size_t astriplen
Definition: iosm.h:276
Structures and prototypes used for an "rpmts" transaction set.
Definition: iosm.h:36
rpmfi fi
Definition: filetriggers.h:15
#define TAR_BLOCK_SIZE
Definition: tar.h:17
int arTrailerWrite(void *_iosm)
Write ar(1) trailer.
Definition: ar.c:309
int strict_erasures
Definition: iosm.h:280
struct Spec_s * Spec
Definition: iosm.c:50
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
#define SUFFIX_RPMORIG
Definition: iosm.c:105
size_t rdsize
Definition: iosm.h:233
char * rdbuf
Definition: iosm.h:230
const char * suffix
Definition: iosm.h:264
struct stat osb
Definition: iosm.h:306
unsigned blksize
Definition: iosm.h:308
static int arSetup(IOSM_t iosm, rpmfi fi)
Definition: iosm.c:596
static int writeLinkedFile(IOSM_t iosm)
Write set of linked files to payload stream.
Definition: iosm.c:1240
int mkdirsdone
Definition: iosm.h:275
static int iosmMakeLinks(IOSM_t iosm)
Create pending hard links to existing file.
Definition: iosm.c:1314
static int dnlIndex(const DNLI_t dnli)
Definition: iosm.c:314
struct rpmmi_s * rpmmi
Definition: iosm.c:48
int debug
Definition: iosm.h:283
static int extractRegular(IOSM_t iosm)
Create file from payload stream.
Definition: iosm.c:1030
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2991
#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
File state machine to handle archive I/O and system call's.
#define _(Text)
Definition: system.h:29
int diskchecked
Definition: iosm.h:273
#define xmalloc
Definition: system.h:32
const char * iosmFileActionString(iosmFileAction a)
Return formatted string representation of file disposition.
Definition: iosm.c:2683
struct rpmdb_s * rpmdb
Definition: iosm.c:47
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1024
static int iosmRmdirs(IOSM_t iosm)
Remove (if created) directories not explicitly included in package.
Definition: iosm.c:1420
const char * baseName
Definition: iosm.h:292
int unameToUid(const char *thisUname, uid_t *uid)
Definition: ugid.c:16
#define D_(Text)
Definition: system.h:526
int exists
Definition: iosm.h:274
int(* headerRead)(void *_iosm, struct stat *st)
Definition: iosm.h:309
const char * rpmsxMatch(rpmsx sx, const char *fn, mode_t mode)
Return security context for a file.
Definition: rpmsx.c:151
unsigned short * dnlx
Definition: iosm.h:267
rpmtransFlags rpmtsFlags(rpmts ts)
Get transaction flags, i.e.
Definition: rpmts.c:1334
int tarHeaderRead(void *_iosm, struct stat *st)
Read tar header from payload.
Definition: tar.c:122
int tarHeaderWrite(void *_iosm, struct stat *st)
Write tar header to payload.
Definition: tar.c:387
#define xrealloc
Definition: system.h:35
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
#define IOSMERR_CHECK_ERRNO
Definition: iosm.h:64
struct iosmIterator_s * IOSMI_t
Iterator across package file info, forward on install, backward on erase.
Definition: iosm.h:184
int j
Definition: mongo.h:438
Definition: iosm.h:33
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397
const char * opath
Definition: iosm.h:224