rpm  5.2.1
rpmfi.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h> /* XXX fnpyKey */
10 #include <rpmlog.h>
11 #include <rpmurl.h> /* XXX urlGetPath */
12 #include <rpmmacro.h> /* XXX rpmCleanPath */
13 #include <ugid.h>
14 
15 #define _RPMAV_INTERNAL /* XXX avOpendir */
16 #include <rpmdav.h>
17 
18 #include <rpmtypes.h>
19 #include <rpmtag.h>
20 
21 #define _IOSM_INTERNAL
22 #define _RPMFI_INTERNAL
23 #include "fsm.h" /* XXX newFSM() */
24 #include "legacy.h" /* XXX dodigest */
25 
26 #include "rpmds.h"
27 
28 #define _RPMTE_INTERNAL /* relocations */
29 #include "rpmte.h"
30 #include "rpmts.h"
31 
32 #include <rpmcli.h> /* XXX rpmHeaderFormats */
33 
34 #include "debug.h"
35 
36 /*@access IOSM_t @*/ /* XXX cast */
37 
38 /*@access rpmte @*/
39 /*@access rpmts @*/ /* XXX cast */
40 
41 /*@access FSM_t @*/ /* XXX fsm->repackaged */
42 /*@access DIR @*/
43 
47 /*@only@*/ /*@null@*/
48  const char * oldPath;
49 /*@only@*/ /*@null@*/
50  const char * newPath;
51 };
52 
53 /*@unchecked@*/
54 int _rpmfi_debug = 0;
55 
62 static /*@only@*/
63 char * stripTrailingChar(/*@only@*/ char * s, char c)
64  /*@modifies *s */
65 {
66  char * t;
67 /*@-boundswrite@*/
68  for (t = s + strlen(s) - 1; *t == c && t >= s; t--)
69  *t = '\0';
70 /*@=boundswrite@*/
71  return s;
72 }
73 
74 int rpmfiFC(rpmfi fi)
75 {
76  return (fi != NULL ? fi->fc : 0);
77 }
78 
79 int rpmfiDC(rpmfi fi)
80 {
81  return (fi != NULL ? fi->dc : 0);
82 }
83 
84 #ifdef NOTYET
85 int rpmfiDI(rpmfi fi)
86 {
87 }
88 #endif
89 
90 int rpmfiFX(rpmfi fi)
91 {
92  return (fi != NULL ? fi->i : -1);
93 }
94 
95 int rpmfiSetFX(rpmfi fi, int fx)
96 {
97  int i = -1;
98 
99  if (fi != NULL && fx >= 0 && fx < (int)fi->fc) {
100  i = fi->i;
101  fi->i = fx;
102  fi->j = fi->dil[fi->i];
103  }
104  return i;
105 }
106 
107 int rpmfiDX(rpmfi fi)
108 {
109  return (fi != NULL ? fi->j : -1);
110 }
111 
112 int rpmfiSetDX(rpmfi fi, int dx)
113 {
114  int j = -1;
115 
116  if (fi != NULL && dx >= 0 && dx < (int)fi->dc) {
117  j = fi->j;
118  fi->j = dx;
119  }
120  return j;
121 }
122 
124 {
125  return (fi != NULL ? fi->isSource : 0);
126 }
127 
128 const char * rpmfiBN(rpmfi fi)
129 {
130  const char * BN = NULL;
131 
132  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
133  if (fi->bnl != NULL)
134  BN = fi->bnl[fi->i];
135  }
136  return BN;
137 }
138 
139 const char * rpmfiDN(rpmfi fi)
140 {
141  const char * DN = NULL;
142 
143  if (fi != NULL && fi->j >= 0 && fi->j < (int)fi->dc) {
144  if (fi->dnl != NULL)
145  DN = fi->dnl[fi->j];
146  }
147  return DN;
148 }
149 
150 const char * rpmfiFN(rpmfi fi)
151 {
152  const char * FN = "";
153 
154  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
155  const char *dn;
156  char * t;
157  if (fi->fn == NULL)
158  fi->fn = xmalloc(fi->fnlen + 1);
159  FN = t = fi->fn;
160  (void) urlPath(fi->dnl[fi->dil[fi->i]], &dn);
161  *t = '\0';
162  t = stpcpy(t, dn);
163  t = stpcpy(t, fi->bnl[fi->i]);
164  }
165  return FN;
166 }
167 
169 {
170  if (fi != NULL)
171  return fi->fnlen;
172  return 0;
173 }
174 
176 {
177  rpmuint32_t FFlags = 0;
178 
179  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
180  if (fi->fflags != NULL)
181  FFlags = fi->fflags[fi->i];
182  }
183  return FFlags;
184 }
185 
187 {
188  rpmuint32_t oFFlags = 0;
189 
190  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
191  if (fi->fflags != NULL && fi->h == NULL) {
192  oFFlags = fi->fflags[fi->i];
193  *((rpmuint32_t *)(fi->fflags + fi->i)) = FFlags;
194  }
195  }
196  return oFFlags;
197 }
198 
200 {
201  rpmuint32_t VFlags = 0;
202 
203  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
204  if (fi->vflags != NULL)
205  VFlags = fi->vflags[fi->i];
206  }
207  return VFlags;
208 }
209 
211 {
212  rpmuint32_t oVFlags = 0;
213 
214  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
215  if (fi->vflags != NULL && fi->h == NULL) {
216  oVFlags = fi->vflags[fi->i];
217  *((rpmuint32_t *)(fi->vflags + fi->i)) = VFlags;
218  }
219  }
220  return oVFlags;
221 }
222 
224 {
225  rpmuint16_t fmode = 0;
226 
227  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
228  if (fi->fmodes != NULL)
229  fmode = fi->fmodes[fi->i];
230  }
231  return fmode;
232 }
233 
235 {
237 
238  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
239  if (fi->fstates != NULL)
240  fstate = fi->fstates[fi->i];
241  }
242  return fstate;
243 }
244 
246 {
247  rpmuint32_t ofstate = 0;
248 
249  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
250  if (fi->fstates != NULL) {
251  ofstate = fi->fstates[fi->i];
252  fi->fstates[fi->i] = fstate;
253  }
254  }
255  return ofstate;
256 }
257 
258 const unsigned char * rpmfiDigest(rpmfi fi, int * algop, size_t * lenp)
259 {
260  unsigned char * digest = NULL;
261 
262  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
263  if (fi->digests != NULL) {
264  digest = fi->digests + (fi->digestlen * fi->i);
265  if (algop != NULL)
266  *algop = (fi->fdigestalgos
267  ? fi->fdigestalgos[fi->i] : fi->digestalgo);
268  if (lenp != NULL)
269  *lenp = fi->digestlen;
270  }
271  }
272  return digest;
273 }
274 
275 const char * rpmfiFLink(rpmfi fi)
276 {
277  const char * flink = NULL;
278 
279  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
280  if (fi->flinks != NULL)
281  flink = fi->flinks[fi->i];
282  }
283  return flink;
284 }
285 
287 {
288  rpmuint32_t fsize = 0;
289 
290  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
291  if (fi->fsizes != NULL)
292  fsize = fi->fsizes[fi->i];
293  }
294  return fsize;
295 }
296 
298 {
299  rpmuint16_t frdev = 0;
300 
301  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
302  if (fi->frdevs != NULL)
303  frdev = fi->frdevs[fi->i];
304  }
305  return frdev;
306 }
307 
309 {
310  rpmuint32_t finode = 0;
311 
312  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
313  if (fi->finodes != NULL)
314  finode = fi->finodes[fi->i];
315  }
316  return finode;
317 }
318 
320 {
321  rpmuint32_t color = 0;
322 
323  if (fi != NULL)
324  /* XXX ignore all but lsnibble for now. */
325  color = fi->color & 0xf;
326  return color;
327 }
328 
330 {
331  rpmuint32_t fcolor = 0;
332 
333  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
334  if (fi->fcolors != NULL)
335  /* XXX ignore all but lsnibble for now. */
336  fcolor = (fi->fcolors[fi->i] & 0x0f);
337  }
338  return fcolor;
339 }
340 
341 const char * rpmfiFClass(rpmfi fi)
342 {
343  const char * fclass = NULL;
344 
345  if (fi != NULL && fi->fcdictx != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
346  int cdictx = fi->fcdictx[fi->i];
347  if (fi->cdict != NULL && cdictx >= 0 && cdictx < (int)fi->ncdict)
348  fclass = fi->cdict[cdictx];
349  }
350  return fclass;
351 }
352 
353 const char * rpmfiFContext(rpmfi fi)
354 {
355  const char * fcontext = NULL;
356 
357  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
358  if (fi->fcontexts != NULL)
359  fcontext = fi->fcontexts[fi->i];
360  }
361  return fcontext;
362 }
363 
365 {
366  int fddictx = -1;
367  int fddictn = 0;
368  const rpmuint32_t * fddict = NULL;
369 
370  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
371  if (fi->fddictn != NULL)
372  fddictn = fi->fddictn[fi->i];
373  if (fddictn > 0 && fi->fddictx != NULL)
374  fddictx = fi->fddictx[fi->i];
375  if (fi->ddict != NULL && fddictx >= 0 && (fddictx+fddictn) <= (int)fi->nddict)
376  fddict = fi->ddict + fddictx;
377  }
378 /*@-dependenttrans -onlytrans @*/
379  if (fddictp)
380  *fddictp = fddict;
381 /*@=dependenttrans =onlytrans @*/
382  return fddictn;
383 }
384 
386 {
387  rpmuint32_t nlink = 0;
388 
389  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
390  /* XXX rpm-2.3.12 has not RPMTAG_FILEINODES */
391  if (fi->finodes && fi->frdevs) {
392  rpmuint32_t finode = fi->finodes[fi->i];
393  rpmuint16_t frdev = fi->frdevs[fi->i];
394  int j;
395 
396  for (j = 0; j < (int)fi->fc; j++) {
397  if (fi->frdevs[j] == frdev && fi->finodes[j] == finode)
398  nlink++;
399  }
400  }
401  }
402  return nlink;
403 }
404 
406 {
407  rpmuint32_t fmtime = 0;
408 
409  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
410  if (fi->fmtimes != NULL)
411  fmtime = fi->fmtimes[fi->i];
412  }
413  return fmtime;
414 }
415 
416 const char * rpmfiFUser(rpmfi fi)
417 {
418  const char * fuser = NULL;
419 
420  /* XXX add support for ancient RPMTAG_FILEUIDS? */
421  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
422  if (fi->fuser != NULL)
423  fuser = fi->fuser[fi->i];
424  }
425  return fuser;
426 }
427 
428 const char * rpmfiFGroup(rpmfi fi)
429 {
430  const char * fgroup = NULL;
431 
432  /* XXX add support for ancient RPMTAG_FILEGIDS? */
433  if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
434  if (fi->fgroup != NULL)
435  fgroup = fi->fgroup[fi->i];
436  }
437  return fgroup;
438 }
439 
440 void * rpmfiExclude(const rpmfi fi)
441 {
442  return (fi != NULL ? fi->exclude : NULL);
443 }
444 
445 int rpmfiNExclude(const rpmfi fi)
446 {
447  return (fi != NULL ? fi->nexclude : 0);
448 }
449 
450 void * rpmfiInclude(const rpmfi fi)
451 {
452  return (fi != NULL ? fi->include : NULL);
453 }
454 
455 int rpmfiNInclude(const rpmfi fi)
456 {
457  return (fi != NULL ? fi->ninclude : 0);
458 }
459 
461 {
462  int i = -1;
463 
464  if (fi != NULL && ++fi->i >= 0) {
465  if (fi->i < (int)fi->fc) {
466  i = fi->i;
467  if (fi->dil != NULL)
468  fi->j = fi->dil[fi->i];
469  } else
470  fi->i = -1;
471 
472 /*@-modfilesys @*/
473 if (_rpmfi_debug < 0 && i != -1)
474 fprintf(stderr, "*** fi %p\t%s[%d] %s%s\n", fi, (fi->Type ? fi->Type : "?Type?"), i, (i >= 0 ? fi->dnl[fi->j] : ""), (i >= 0 ? fi->bnl[fi->i] : ""));
475 /*@=modfilesys @*/
476 
477  }
478 
479  return i;
480 }
481 
482 rpmfi rpmfiInit(rpmfi fi, int fx)
483 {
484  if (fi != NULL) {
485  if (fx >= 0 && fx < (int)fi->fc) {
486  fi->i = fx - 1;
487  fi->j = -1;
488  }
489  }
490 
491  /*@-refcounttrans@*/
492  return fi;
493  /*@=refcounttrans@*/
494 }
495 
497 {
498  int j = -1;
499 
500  if (fi != NULL && ++fi->j >= 0) {
501  if (fi->j < (int)fi->dc)
502  j = fi->j;
503  else
504  fi->j = -1;
505 
506 /*@-modfilesys @*/
507 if (_rpmfi_debug < 0 && j != -1)
508 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, (fi->Type ? fi->Type : "?Type?"), j);
509 /*@=modfilesys @*/
510 
511  }
512 
513  return j;
514 }
515 
516 rpmfi rpmfiInitD(rpmfi fi, int dx)
517 {
518  if (fi != NULL) {
519  if (dx >= 0 && dx < (int)fi->fc)
520  fi->j = dx - 1;
521  else
522  fi = NULL;
523  }
524 
525  /*@-refcounttrans@*/
526  return fi;
527  /*@=refcounttrans@*/
528 }
529 
535 static /*@observer@*/
536 const char * rpmfiFtstring (rpmFileTypes ft)
537  /*@*/
538 {
539  switch (ft) {
540  case XDIR: return "directory";
541  case CDEV: return "char dev";
542  case BDEV: return "block dev";
543  case LINK: return "link";
544  case SOCK: return "sock";
545  case PIPE: return "fifo/pipe";
546  case REG: return "file";
547  default: return "unknown file type";
548  }
549  /*@notreached@*/
550 }
551 
558  /*@*/
559 {
560  if (S_ISDIR(mode)) return XDIR;
561  if (S_ISCHR(mode)) return CDEV;
562  if (S_ISBLK(mode)) return BDEV;
563  if (S_ISLNK(mode)) return LINK;
564 /*@-unrecog@*/
565  if (S_ISSOCK(mode)) return SOCK;
566 /*@=unrecog@*/
567  if (S_ISFIFO(mode)) return PIPE;
568  return REG;
569 }
570 
571 int rpmfiCompare(const rpmfi afi, const rpmfi bfi)
572  /*@*/
573 {
574  rpmFileTypes awhat = rpmfiWhatis(rpmfiFMode(afi));
575  rpmFileTypes bwhat = rpmfiWhatis(rpmfiFMode(bfi));
576 
577  if (awhat != bwhat) return 1;
578 
579  if (awhat == LINK) {
580  const char * alink = rpmfiFLink(afi);
581  const char * blink = rpmfiFLink(bfi);
582  if (alink == blink) return 0;
583  if (alink == NULL) return 1;
584  if (blink == NULL) return -1;
585  return strcmp(alink, blink);
586  } else if (awhat == REG) {
587  int aalgo = 0;
588  size_t alen = 0;
589  const unsigned char * adigest = rpmfiDigest(afi, &aalgo, &alen);
590  int balgo = 0;
591  size_t blen = 0;
592  const unsigned char * bdigest = rpmfiDigest(bfi, &balgo, &blen);
593  /* XXX W2DO? changing file digest algo may break rpmfiCompare. */
594  if (!(aalgo == balgo && alen == blen))
595  return -1;
596  if (adigest == bdigest) return 0;
597  if (adigest == NULL) return 1;
598  if (bdigest == NULL) return -1;
599  return memcmp(adigest, bdigest, alen);
600  }
601 
602  return 0;
603 }
604 
605 int rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
606 {
607  const char * fn = rpmfiFN(nfi);
608  int newFlags = rpmfiFFlags(nfi);
609  char buffer[1024+1];
610  rpmFileTypes dbWhat, newWhat, diskWhat;
611  struct stat sb;
612  int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
613 
614  if (Lstat(fn, &sb)) {
615  /*
616  * The file doesn't exist on the disk. Create it unless the new
617  * package has marked it as missingok, or allfiles is requested.
618  */
619  if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) {
620  rpmlog(RPMLOG_DEBUG, D_("%s skipped due to missingok flag\n"),
621  fn);
622  return FA_SKIP;
623  } else {
624  return FA_CREATE;
625  }
626  }
627 
628  diskWhat = rpmfiWhatis((rpmuint16_t)sb.st_mode);
629  dbWhat = rpmfiWhatis(rpmfiFMode(ofi));
630  newWhat = rpmfiWhatis(rpmfiFMode(nfi));
631 
632  /*
633  * RPM >= 2.3.10 shouldn't create config directories -- we'll ignore
634  * them in older packages as well.
635  */
636  if (newWhat == XDIR)
637  return FA_CREATE;
638 
639  if (diskWhat != newWhat && dbWhat != REG && dbWhat != LINK)
640  return save;
641  else if (newWhat != dbWhat && diskWhat != dbWhat)
642  return save;
643  else if (dbWhat != newWhat)
644  return FA_CREATE;
645  else if (dbWhat != LINK && dbWhat != REG)
646  return FA_CREATE;
647 
648  /*
649  * This order matters - we'd prefer to CREATE the file if at all
650  * possible in case something else (like the timestamp) has changed.
651  */
652  memset(buffer, 0, sizeof(buffer));
653  if (dbWhat == REG) {
654  int oalgo = 0;
655  size_t olen = 0;
656  const unsigned char * odigest;
657  int nalgo = 0;
658  size_t nlen = 0;
659  const unsigned char * ndigest;
660  odigest = rpmfiDigest(ofi, &oalgo, &olen);
661  if (diskWhat == REG) {
662  if (!(newFlags & RPMFILE_SPARSE))
663  if (dodigest(oalgo, fn, (unsigned char *)buffer, 0, NULL))
664  return FA_CREATE; /* assume file has been removed */
665  if (odigest && !memcmp(odigest, buffer, olen))
666  return FA_CREATE; /* unmodified config file, replace. */
667  }
668  ndigest = rpmfiDigest(nfi, &nalgo, &nlen);
669 /*@-nullpass@*/
670  if (odigest && ndigest && oalgo == nalgo && olen == nlen
671  && !memcmp(odigest, ndigest, nlen))
672  return FA_SKIP; /* identical file, don't bother. */
673 /*@=nullpass@*/
674  } else /* dbWhat == LINK */ {
675  const char * oFLink, * nFLink;
676  oFLink = rpmfiFLink(ofi);
677  if (diskWhat == LINK) {
678  if (Readlink(fn, buffer, sizeof(buffer) - 1) == -1)
679  return FA_CREATE; /* assume file has been removed */
680  buffer[sizeof(buffer)-1] = '\0';
681  if (oFLink && !strcmp(oFLink, buffer))
682  return FA_CREATE; /* unmodified config file, replace. */
683  }
684  nFLink = rpmfiFLink(nfi);
685 /*@-nullpass@*/
686  if (oFLink && nFLink && !strcmp(oFLink, nFLink))
687  return FA_SKIP; /* identical file, don't bother. */
688 /*@=nullpass@*/
689  }
690 
691  /*
692  * The config file on the disk has been modified, but
693  * the ones in the two packages are different. It would
694  * be nice if RPM was smart enough to at least try and
695  * merge the difference ala CVS, but...
696  */
697  return save;
698 }
699 
700 /*@observer@*/
701 const char * rpmfiTypeString(rpmfi fi)
702 {
703  switch(rpmteType(fi->te)) {
704  case TR_ADDED: return " install";
705  case TR_REMOVED: return " erase";
706  default: return "???";
707  }
708  /*@noteached@*/
709 }
710 
711 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
712 
722 static
724  Header origH, iosmFileAction * actions)
725  /*@globals rpmGlobalMacroContext, h_errno,
726  internalState @*/
727  /*@modifies ts, fi, origH, actions, rpmGlobalMacroContext,
728  internalState @*/
729 {
730  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
731  rpmte p = rpmtsRelocateElement(ts);
732  static int _printed = 0;
733  int allowBadRelocate = (rpmtsFilterFlags(ts) & RPMPROB_FILTER_FORCERELOCATE);
734  rpmRelocation relocations = NULL;
735  int numRelocations;
736  const char ** validRelocations;
737  rpmTagType validType;
738  int numValid;
739  const char ** baseNames;
740  const char ** dirNames;
741  rpmuint32_t * dirIndexes;
742  rpmuint32_t fileCount;
743  rpmuint32_t dirCount;
744  rpmuint32_t mydColor = rpmExpandNumeric("%{?_autorelocate_dcolor}");
745  rpmuint32_t * fFlags = NULL;
746  rpmuint32_t * fColors = NULL;
747  rpmuint32_t * dColors = NULL;
748  rpmuint16_t * fModes = NULL;
749  Header h;
750  int nrelocated = 0;
751  size_t fileAlloced = 0;
752  char * fn = NULL;
753  int haveRelocatedFile = 0;
754  int reldel = 0;
755  size_t len;
756  int i, j;
757  int xx;
758 
759  he->tag = RPMTAG_PREFIXES;
760  xx = headerGet(origH, he, 0);
761  validType = he->t;
762  validRelocations = he->p.argv;
763  numValid = he->c;
764  if (!xx)
765  numValid = 0;
766 
767 assert(p != NULL);
768  numRelocations = 0;
769  if (p->relocs)
770  while (p->relocs[numRelocations].newPath ||
771  p->relocs[numRelocations].oldPath)
772  numRelocations++;
773 
774  /*
775  * If no relocations are specified (usually the case), then return the
776  * original header. If there are prefixes, however, then INSTPREFIXES
777  * should be added, but, since relocateFileList() can be called more
778  * than once for the same header, don't bother if already present.
779  */
780  if (p->relocs == NULL || numRelocations == 0) {
781  if (numValid) {
782  if (!headerIsEntry(origH, RPMTAG_INSTPREFIXES)) {
783  he->tag = RPMTAG_INSTPREFIXES;
784  he->t = validType;
785  he->p.argv = validRelocations;
786  he->c = numValid;
787  xx = headerPut(origH, he, 0);
788  }
789  validRelocations = _free(validRelocations);
790  }
791  /* XXX FIXME multilib file actions need to be checked. */
792 /*@-castexpose@*/
793  return headerLink(origH);
794 /*@=castexpose@*/
795  }
796 
797 /*@-castexpose@*/
798  h = headerLink(origH);
799 /*@=castexpose@*/
800 
801  relocations = alloca(sizeof(*relocations) * numRelocations);
802 
803  /* Build sorted relocation list from raw relocations. */
804  for (i = 0; i < numRelocations; i++) {
805  char * t;
806 
807  /*
808  * Default relocations (oldPath == NULL) are handled in the UI,
809  * not rpmlib.
810  */
811  if (p->relocs[i].oldPath == NULL) continue; /* XXX can't happen */
812 
813  /* FIXME: Trailing /'s will confuse us greatly. Internal ones will
814  too, but those are more trouble to fix up. :-( */
815  t = alloca_strdup(p->relocs[i].oldPath);
816  relocations[i].oldPath = (t[0] == '/' && t[1] == '\0')
817  ? t
818  : stripTrailingChar(t, '/');
819 
820  /* An old path w/o a new path is valid, and indicates exclusion */
821  if (p->relocs[i].newPath) {
822  int del;
823 
824  t = alloca_strdup(p->relocs[i].newPath);
825  relocations[i].newPath = (t[0] == '/' && t[1] == '\0')
826  ? t
827  : stripTrailingChar(t, '/');
828 
829  /*@-nullpass@*/ /* FIX: relocations[i].oldPath == NULL */
830  /* Verify that the relocation's old path is in the header. */
831  for (j = 0; j < numValid; j++) {
832  if (!strcmp(validRelocations[j], relocations[i].oldPath))
833  /*@innerbreak@*/ break;
834  }
835 
836  /* XXX actions check prevents problem from being appended twice. */
837  if (j == numValid && !allowBadRelocate && actions) {
838  rpmps ps = rpmtsProblems(ts);
840  rpmteNEVR(p), rpmteKey(p),
841  relocations[i].oldPath, NULL, NULL, 0);
842  ps = rpmpsFree(ps);
843  }
844  del =
845  (int)strlen(relocations[i].newPath) - (int)strlen(relocations[i].oldPath);
846  /*@=nullpass@*/
847 
848  if (del > reldel)
849  reldel = del;
850  } else {
851  relocations[i].newPath = NULL;
852  }
853  }
854 
855  /* stupid bubble sort, but it's probably faster here */
856  for (i = 0; i < numRelocations; i++) {
857  int madeSwap;
858  madeSwap = 0;
859  for (j = 1; j < numRelocations; j++) {
860  struct rpmRelocation_s tmpReloc;
861  if (relocations[j - 1].oldPath == NULL || /* XXX can't happen */
862  relocations[j ].oldPath == NULL || /* XXX can't happen */
863  strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0)
864  /*@innercontinue@*/ continue;
865  /*@-usereleased@*/ /* LCL: ??? */
866  tmpReloc = relocations[j - 1];
867  relocations[j - 1] = relocations[j];
868  relocations[j] = tmpReloc;
869  /*@=usereleased@*/
870  madeSwap = 1;
871  }
872  if (!madeSwap) break;
873  }
874 
875  if (!_printed) {
876  _printed = 1;
877  rpmlog(RPMLOG_DEBUG, D_("========== relocations\n"));
878  for (i = 0; i < numRelocations; i++) {
879  if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */
880  if (relocations[i].newPath == NULL)
881  rpmlog(RPMLOG_DEBUG, D_("%5d exclude %s\n"),
882  i, relocations[i].oldPath);
883  else
884  rpmlog(RPMLOG_DEBUG, D_("%5d relocate %s -> %s\n"),
885  i, relocations[i].oldPath, relocations[i].newPath);
886  }
887  }
888 
889  /* Add relocation values to the header */
890  if (numValid) {
891  const char ** actualRelocations;
892  int numActual;
893 
894  actualRelocations = xmalloc(numValid * sizeof(*actualRelocations));
895  numActual = 0;
896  for (i = 0; i < numValid; i++) {
897  for (j = 0; j < numRelocations; j++) {
898  if (relocations[j].oldPath == NULL || /* XXX can't happen */
899  strcmp(validRelocations[i], relocations[j].oldPath))
900  /*@innercontinue@*/ continue;
901  /* On install, a relocate to NULL means skip the path. */
902  if (relocations[j].newPath) {
903  actualRelocations[numActual] = relocations[j].newPath;
904  numActual++;
905  }
906  /*@innerbreak@*/ break;
907  }
908  if (j == numRelocations) {
909  actualRelocations[numActual] = validRelocations[i];
910  numActual++;
911  }
912  }
913 
914  if (numActual) {
915  he->tag = RPMTAG_INSTPREFIXES;
916  he->t = RPM_STRING_ARRAY_TYPE;
917  he->p.argv = actualRelocations;
918  he->c = numActual;
919  xx = headerPut(h, he, 0);
920  }
921 
922  actualRelocations = _free(actualRelocations);
923  validRelocations = _free(validRelocations);
924  }
925 
926  he->tag = RPMTAG_BASENAMES;
927  xx = headerGet(h, he, 0);
928  baseNames = he->p.argv;
929  fileCount = he->c;
930  he->tag = RPMTAG_DIRINDEXES;
931  xx = headerGet(h, he, 0);
932  dirIndexes = he->p.ui32p;
933  he->tag = RPMTAG_DIRNAMES;
934  xx = headerGet(h, he, 0);
935  dirNames = he->p.argv;
936  dirCount = he->c;
937  he->tag = RPMTAG_FILEFLAGS;
938  xx = headerGet(h, he, 0);
939  fFlags = he->p.ui32p;
940  he->tag = RPMTAG_FILECOLORS;
941  xx = headerGet(h, he, 0);
942  fColors = he->p.ui32p;
943  he->tag = RPMTAG_FILEMODES;
944  xx = headerGet(h, he, 0);
945  fModes = he->p.ui16p;
946 
947  dColors = alloca(dirCount * sizeof(*dColors));
948  memset(dColors, 0, dirCount * sizeof(*dColors));
949 
950  /*
951  * For all relocations, we go through sorted file/relocation lists
952  * backwards so that /usr/local relocations take precedence over /usr
953  * ones.
954  */
955 
956  /* Relocate individual paths. */
957 
958  for (i = fileCount - 1; i >= 0; i--) {
959  rpmFileTypes ft;
960  size_t fnlen;
961 
962  len = reldel +
963  strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
964  if (len >= fileAlloced) {
965  fileAlloced = len * 2;
966  fn = xrealloc(fn, fileAlloced);
967  }
968 
969 assert(fn != NULL); /* XXX can't happen */
970  *fn = '\0';
971  fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn;
972 
973 if (fColors != NULL) {
974 /* XXX pkgs may not have unique dirNames, so color all dirNames that match. */
975 for (j = 0; j < (int)dirCount; j++) {
976 if (strcmp(dirNames[dirIndexes[i]], dirNames[j])) /*@innercontinue@*/ continue;
977 dColors[j] |= fColors[i];
978 }
979 }
980 
981  /*
982  * See if this file path needs relocating.
983  */
984  /*
985  * XXX FIXME: Would a bsearch of the (already sorted)
986  * relocation list be a good idea?
987  */
988  for (j = numRelocations - 1; j >= 0; j--) {
989  if (relocations[j].oldPath == NULL) /* XXX can't happen */
990  /*@innercontinue@*/ continue;
991  len = strcmp(relocations[j].oldPath, "/")
992  ? strlen(relocations[j].oldPath)
993  : 0;
994 
995  if (fnlen < len)
996  /*@innercontinue@*/ continue;
997  /*
998  * Only subdirectories or complete file paths may be relocated. We
999  * don't check for '\0' as our directory names all end in '/'.
1000  */
1001  if (!(fn[len] == '/' || fnlen == len))
1002  /*@innercontinue@*/ continue;
1003 
1004  if (strncmp(relocations[j].oldPath, fn, len))
1005  /*@innercontinue@*/ continue;
1006  /*@innerbreak@*/ break;
1007  }
1008  if (j < 0) continue;
1009 
1010 /*@-nullderef@*/ /* FIX: fModes may be NULL */
1011  ft = rpmfiWhatis(fModes[i]);
1012 /*@=nullderef@*/
1013 
1014  /* On install, a relocate to NULL means skip the path. */
1015  if (relocations[j].newPath == NULL) {
1016  if (ft == XDIR) {
1017  /* Start with the parent, looking for directory to exclude. */
1018  for (j = dirIndexes[i]; j < (int)dirCount; j++) {
1019  len = strlen(dirNames[j]) - 1;
1020  while (len > 0 && dirNames[j][len-1] == '/') len--;
1021  if (fnlen != len)
1022  /*@innercontinue@*/ continue;
1023  if (strncmp(fn, dirNames[j], fnlen))
1024  /*@innercontinue@*/ continue;
1025  /*@innerbreak@*/ break;
1026  }
1027  }
1028  if (actions) {
1029  actions[i] = FA_SKIPNSTATE;
1030  rpmlog(RPMLOG_DEBUG, D_("excluding %s %s\n"),
1031  rpmfiFtstring(ft), fn);
1032  }
1033  continue;
1034  }
1035 
1036  /* Relocation on full paths only, please. */
1037  if (fnlen != len) continue;
1038 
1039  if (actions)
1040  rpmlog(RPMLOG_DEBUG, D_("relocating %s to %s\n"),
1041  fn, relocations[j].newPath);
1042  nrelocated++;
1043 
1044  strcpy(fn, relocations[j].newPath);
1045  { char * te = strrchr(fn, '/');
1046  if (te) {
1047  if (te > fn) te++; /* root is special */
1048  fnlen = te - fn;
1049  } else
1050  te = fn + strlen(fn);
1051  /*@-nullpass -nullderef@*/ /* LCL: te != NULL here. */
1052  if (strcmp(baseNames[i], te)) /* basename changed too? */
1053  baseNames[i] = alloca_strdup(te);
1054  *te = '\0'; /* terminate new directory name */
1055  /*@=nullpass =nullderef@*/
1056  }
1057 
1058  /* Does this directory already exist in the directory list? */
1059  for (j = 0; j < (int)dirCount; j++) {
1060  if (fnlen != strlen(dirNames[j]))
1061  /*@innercontinue@*/ continue;
1062  if (strncmp(fn, dirNames[j], fnlen))
1063  /*@innercontinue@*/ continue;
1064  /*@innerbreak@*/ break;
1065  }
1066 
1067  if (j < (int)dirCount) {
1068  dirIndexes[i] = j;
1069  continue;
1070  }
1071 
1072  /* Creating new paths is a pita */
1073  if (!haveRelocatedFile) {
1074  const char ** newDirList;
1075 
1076  haveRelocatedFile = 1;
1077  newDirList = xmalloc((dirCount + 1) * sizeof(*newDirList));
1078  for (j = 0; j < (int)dirCount; j++)
1079  newDirList[j] = alloca_strdup(dirNames[j]);
1080  dirNames = _free(dirNames);
1081  dirNames = newDirList;
1082  } else {
1083  dirNames = xrealloc(dirNames,
1084  sizeof(*dirNames) * (dirCount + 1));
1085  }
1086 
1087  dirNames[dirCount] = alloca_strdup(fn);
1088  dirIndexes[i] = dirCount;
1089  dirCount++;
1090  }
1091 
1092  /* Finish off by relocating directories. */
1093  for (i = dirCount - 1; i >= 0; i--) {
1094  for (j = numRelocations - 1; j >= 0; j--) {
1095 
1096  /* XXX Don't autorelocate uncolored directories. */
1097  if (j == p->autorelocatex
1098  && (dColors[i] == 0 || !(dColors[i] & mydColor)))
1099  /*@innercontinue@*/ continue;
1100 
1101  if (relocations[j].oldPath == NULL) /* XXX can't happen */
1102  /*@innercontinue@*/ continue;
1103  len = strcmp(relocations[j].oldPath, "/")
1104  ? strlen(relocations[j].oldPath)
1105  : 0;
1106 
1107  if (len && strncmp(relocations[j].oldPath, dirNames[i], len))
1108  /*@innercontinue@*/ continue;
1109 
1110  /*
1111  * Only subdirectories or complete file paths may be relocated. We
1112  * don't check for '\0' as our directory names all end in '/'.
1113  */
1114  if (dirNames[i][len] != '/')
1115  /*@innercontinue@*/ continue;
1116 
1117  if (relocations[j].newPath) { /* Relocate the path */
1118  const char * s = relocations[j].newPath;
1119  char * t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1);
1120  size_t slen;
1121 
1122  (void) stpcpy( stpcpy(t, s) , dirNames[i] + len);
1123 
1124  /* Unfortunatly rpmCleanPath strips the trailing slash.. */
1125  (void) rpmCleanPath(t);
1126  slen = strlen(t);
1127  t[slen] = '/';
1128  t[slen+1] = '\0';
1129 
1130  if (actions)
1132  D_("relocating directory %s to %s\n"), dirNames[i], t);
1133  dirNames[i] = t;
1134  nrelocated++;
1135  }
1136  }
1137  }
1138 
1139  /* Save original filenames in header and replace (relocated) filenames. */
1140  if (nrelocated) {
1141  he->tag = RPMTAG_BASENAMES;
1142  xx = headerGet(h, he, 0);
1143  he->tag = RPMTAG_ORIGBASENAMES;
1144  xx = headerPut(h, he, 0);
1145  he->p.ptr = _free(he->p.ptr);
1146 
1147  he->tag = RPMTAG_DIRNAMES;
1148  xx = headerGet(h, he, 0);
1149  he->tag = RPMTAG_ORIGDIRNAMES;
1150  xx = headerPut(h, he, 0);
1151  he->p.ptr = _free(he->p.ptr);
1152 
1153  he->tag = RPMTAG_DIRINDEXES;
1154  xx = headerGet(h, he, 0);
1155  he->tag = RPMTAG_ORIGDIRINDEXES;
1156  xx = headerPut(h, he, 0);
1157  he->p.ptr = _free(he->p.ptr);
1158 
1159  he->tag = RPMTAG_BASENAMES;
1160  he->t = RPM_STRING_ARRAY_TYPE;
1161  he->p.argv = baseNames;
1162  he->c = fileCount;
1163  xx = headerMod(h, he, 0);
1164  fi->bnl = _free(fi->bnl);
1165  xx = headerGet(h, he, 0);
1166 /*@-dependenttrans@*/
1167  fi->bnl = he->p.argv;
1168 /*@=dependenttrans@*/
1169  fi->fc = he->c;
1170 
1171  he->tag = RPMTAG_DIRNAMES;
1172  he->t = RPM_STRING_ARRAY_TYPE;
1173  he->p.argv = dirNames;
1174  he->c = dirCount;
1175  xx = headerMod(h, he, 0);
1176  fi->dnl = _free(fi->dnl);
1177  xx = headerGet(h, he, 0);
1178  fi->dnl = he->p.argv;
1179  fi->dc = he->c;
1180 
1181  he->tag = RPMTAG_DIRINDEXES;
1182  he->t = RPM_UINT32_TYPE;
1183  he->p.ui32p = dirIndexes;
1184  he->c = fileCount;
1185  xx = headerMod(h, he, 0);
1186  fi->dil = _free(fi->dil);
1187  xx = headerGet(h, he, 0);
1188 /*@-dependenttrans@*/
1189  fi->dil = he->p.ui32p;
1190 /*@=dependenttrans@*/
1191  }
1192 
1193  baseNames = _free(baseNames);
1194  dirIndexes = _free(dirIndexes);
1195  dirNames = _free(dirNames);
1196  fFlags = _free(fFlags);
1197  fColors = _free(fColors);
1198  fModes = _free(fModes);
1199 
1200 /*@-dependenttrans@*/
1201  fn = _free(fn);
1202 /*@=dependenttrans@*/
1203 
1204 /*@-retalias@*/
1205  return h;
1206 /*@=retalias@*/
1207 }
1208 
1210 {
1211  if (fi->h != NULL)
1212  (void)headerFree(fi->h);
1213  fi->h = NULL;
1214 /*@-assignexpose -castexpose @*/
1215  if (h != NULL)
1216  fi->h = headerLink(h);
1217 /*@=assignexpose =castexpose @*/
1218  return 0;
1219 }
1220 
1221 static void rpmfiFini(void * _fi)
1222  /*@modifies *_fi @*/
1223 {
1224  rpmfi fi = _fi;
1225 
1226  /* Free pre- and post-transaction script and interpreter strings. */
1227  fi->pretrans = _free(fi->pretrans);
1228  fi->pretransprog = _free(fi->pretransprog);
1229  fi->posttrans = _free(fi->posttrans);
1230  fi->posttransprog = _free(fi->posttransprog);
1231  fi->verifyscript = _free(fi->verifyscript);
1232  fi->verifyscriptprog = _free(fi->verifyscriptprog);
1233 
1234  if (fi->fc > 0) {
1235  fi->bnl = _free(fi->bnl);
1236  fi->dnl = _free(fi->dnl);
1237 
1238  fi->flinks = _free(fi->flinks);
1239  fi->flangs = _free(fi->flangs);
1240  fi->fdigests = _free(fi->fdigests);
1241  fi->digests = _free(fi->digests);
1242 
1243  fi->cdict = _free(fi->cdict);
1244 
1245  fi->fuser = _free(fi->fuser);
1246  fi->fgroup = _free(fi->fgroup);
1247 
1248  fi->fstates = _free(fi->fstates);
1249 
1250  fi->fmtimes = _free(fi->fmtimes);
1251  fi->fmodes = _free(fi->fmodes);
1252  fi->fflags = _free(fi->fflags);
1253  fi->vflags = _free(fi->vflags);
1254  fi->fsizes = _free(fi->fsizes);
1255  fi->frdevs = _free(fi->frdevs);
1256  fi->finodes = _free(fi->finodes);
1257  fi->dil = _free(fi->dil);
1258 
1259  fi->fcolors = _free(fi->fcolors);
1260  fi->fcdictx = _free(fi->fcdictx);
1261  fi->ddict = _free(fi->ddict);
1262  fi->fddictx = _free(fi->fddictx);
1263  fi->fddictn = _free(fi->fddictn);
1264  }
1265 
1266 /*@-globs@*/ /* Avoid rpmGlobalMacroContext */
1267  fi->fsm = freeFSM(fi->fsm);
1268 /*@=globs@*/
1269 
1270  fi->exclude = mireFreeAll(fi->exclude, fi->nexclude);
1271  fi->include = mireFreeAll(fi->include, fi->ninclude);
1272 
1273  fi->fn = _free(fi->fn);
1274  fi->apath = _free(fi->apath);
1275  fi->fmapflags = _free(fi->fmapflags);
1276 
1277  fi->obnl = _free(fi->obnl);
1278  fi->odnl = _free(fi->odnl);
1279 
1280  fi->fcontexts = _free(fi->fcontexts);
1281 
1282  fi->actions = _free(fi->actions);
1283  fi->replacedSizes = _free(fi->replacedSizes);
1284 
1285  (void)headerFree(fi->h);
1286  fi->h = NULL;
1287 }
1288 
1289 /*@unchecked@*/ /*@only@*/ /*@null@*/
1291 
1292 static rpmfi rpmfiGetPool(/*@null@*/ rpmioPool pool)
1293  /*@globals _rpmfiPool, fileSystem, internalState @*/
1294  /*@modifies pool, _rpmfiPool, fileSystem, internalState @*/
1295 {
1296  rpmfi fi;
1297 
1298  if (_rpmfiPool == NULL) {
1299  _rpmfiPool = rpmioNewPool("fi", sizeof(*fi), -1, _rpmfi_debug,
1300  NULL, NULL, rpmfiFini);
1301  pool = _rpmfiPool;
1302  }
1303  return (rpmfi) rpmioGetPool(pool, sizeof(*fi));
1304 }
1305 
1311 static inline unsigned char nibble(char c)
1312  /*@*/
1313 {
1314  if (c >= '0' && c <= '9')
1315  return (c - '0');
1316  if (c >= 'A' && c <= 'F')
1317  return (c - 'A') + 10;
1318  if (c >= 'a' && c <= 'f')
1319  return (c - 'a') + 10;
1320  return 0;
1321 }
1322 
1323 #define _fdupestring(_h, _tag, _data) \
1324  he->tag = _tag; \
1325  xx = headerGet((_h), he, 0); \
1326  _data = he->p.str;
1327 
1328 #define _fdupedata(_h, _tag, _data) \
1329  he->tag = _tag; \
1330  xx = headerGet((_h), he, 0); \
1331  _data = he->p.ptr;
1332 
1333 rpmfi rpmfiNew(const void * _ts, Header h, rpmTag tagN, int flags)
1334 {
1335 /*@-castexpose@*/
1336  const rpmts ts = (const rpmts) _ts;
1337 /*@=castexpose@*/
1338  int scareMem = (flags & 0x1);
1339  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1340  rpmte p;
1341  rpmfi fi = NULL;
1342  const char * Type;
1343  unsigned char * t;
1344  pgpHashAlgo dalgo;
1345  int xx;
1346  int i;
1347 
1348 assert(scareMem == 0); /* XXX always allocate memory */
1349  if (tagN == RPMTAG_BASENAMES) {
1350  Type = "Files";
1351  } else {
1352  Type = "?Type?";
1353  goto exit;
1354  }
1355 
1356  fi = rpmfiGetPool(_rpmfiPool);
1357  if (fi == NULL) /* XXX can't happen */
1358  goto exit;
1359 
1360  fi->magic = RPMFIMAGIC;
1361  fi->Type = Type;
1362  fi->i = -1;
1363  fi->tagN = tagN;
1364 
1365  fi->h = NULL;
1366  fi->isSource =
1367  (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
1368  headerIsEntry(h, RPMTAG_RPMVERSION) != 0 &&
1369  headerIsEntry(h, RPMTAG_ARCH) != 0);
1370 
1371  if (fi->fsm == NULL)
1372  fi->fsm = newFSM();
1373 
1374  ((FSM_t)fi->fsm)->repackaged = (headerIsEntry(h, RPMTAG_REMOVETID) ? 1 : 0);
1375 
1376  /* 0 means unknown */
1377  he->tag = RPMTAG_ARCHIVESIZE;
1378  xx = headerGet(h, he, 0);
1379  fi->archivePos = 0;
1380  fi->archiveSize = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
1381  he->p.ptr = _free(he->p.ptr);
1382 
1383  /* Extract pre- and post-transaction script and interpreter strings. */
1384  _fdupestring(h, RPMTAG_PRETRANS, fi->pretrans);
1385  _fdupestring(h, RPMTAG_PRETRANSPROG, fi->pretransprog);
1386  _fdupestring(h, RPMTAG_POSTTRANS, fi->posttrans);
1387  _fdupestring(h, RPMTAG_POSTTRANSPROG, fi->posttransprog);
1388  _fdupestring(h, RPMTAG_VERIFYSCRIPT, fi->verifyscript);
1389  _fdupestring(h, RPMTAG_VERIFYSCRIPTPROG, fi->verifyscriptprog);
1390 
1391  he->tag = RPMTAG_BASENAMES;
1392  xx = headerGet(h, he, 0);
1393  /* XXX 3.0.x SRPM's can be used, relative fn's at RPMTAG_OLDFILENAMES. */
1394  if (xx == 0 && fi->isSource) {
1395  he->tag = RPMTAG_OLDFILENAMES;
1396  xx = headerGet(h, he, 0);
1397  }
1398  fi->bnl = he->p.argv;
1399  fi->fc = he->c;
1400  if (!xx) {
1401  fi->fc = 0;
1402  fi->dc = 0;
1403  goto exit;
1404  }
1405  _fdupedata(h, RPMTAG_DIRNAMES, fi->dnl);
1406  fi->dc = he->c;
1407  /* XXX 3.0.x SRPM's can be used, relative fn's at RPMTAG_OLDFILENAMES. */
1408  if (fi->dc == 0 && fi->isSource) {
1409  fi->dc = 1;
1410  fi->dnl = xcalloc(3, sizeof(*fi->dnl));
1411  fi->dnl[0] = (const char *)&fi->dnl[2];
1412  fi->dil = xcalloc(fi->fc, sizeof(*fi->dil));
1413  } else {
1414  _fdupedata(h, RPMTAG_DIRINDEXES, fi->dil);
1415  }
1416  _fdupedata(h, RPMTAG_FILEMODES, fi->fmodes);
1417  _fdupedata(h, RPMTAG_FILEFLAGS, fi->fflags);
1418  _fdupedata(h, RPMTAG_FILEVERIFYFLAGS, fi->vflags);
1419  _fdupedata(h, RPMTAG_FILESIZES, fi->fsizes);
1420 
1421  _fdupedata(h, RPMTAG_FILECOLORS, fi->fcolors);
1422  fi->color = 0;
1423  if (fi->fcolors != NULL)
1424  for (i = 0; i < (int)fi->fc; i++)
1425  fi->color |= fi->fcolors[i];
1426  _fdupedata(h, RPMTAG_CLASSDICT, fi->cdict);
1427  fi->ncdict = he->c;
1428  _fdupedata(h, RPMTAG_FILECLASS, fi->fcdictx);
1429 
1430  _fdupedata(h, RPMTAG_DEPENDSDICT, fi->ddict);
1431  fi->nddict = he->c;
1432  _fdupedata(h, RPMTAG_FILEDEPENDSX, fi->fddictx);
1433  _fdupedata(h, RPMTAG_FILEDEPENDSN, fi->fddictn);
1434 
1435  _fdupedata(h, RPMTAG_FILESTATES, fi->fstates);
1436  if (xx == 0 || fi->fstates == NULL)
1437  fi->fstates = xcalloc(fi->fc, sizeof(*fi->fstates));
1438 
1439  fi->action = FA_UNKNOWN;
1440  fi->flags = 0;
1441 
1442 if (fi->actions == NULL)
1443  fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
1444 
1445  /* XXX TR_REMOVED needs IOSM_MAP_{ABSOLUTE,ADDDOT} IOSM_ALL_HARDLINKS */
1446  fi->mapflags =
1448 
1449  _fdupedata(h, RPMTAG_FILELINKTOS, fi->flinks);
1450  _fdupedata(h, RPMTAG_FILELANGS, fi->flangs);
1451 
1452  dalgo = PGPHASHALGO_ERROR;
1453  fi->fdigestalgos = NULL;
1454  _fdupedata(h, RPMTAG_FILEDIGESTALGOS, fi->fdigestalgos);
1455  if (fi->fdigestalgos) {
1456  /* XXX Insure that all algorithms are either 0 or constant. */
1457  for (i = 0; i < (int)fi->fc; i++) {
1458  if (fi->fdigestalgos[i] == 0)
1459  continue;
1460  if (dalgo == PGPHASHALGO_ERROR)
1461  dalgo = (fi->fdigestalgos[i] & 0xff);
1462  else
1463 assert(dalgo == (pgpHashAlgo)fi->fdigestalgos[i]);
1464  }
1465  fi->fdigestalgos = _free(fi->fdigestalgos);
1466  } else {
1467  he->tag = RPMTAG_FILEDIGESTALGO;
1468  xx = headerGet(h, he, 0);
1469  if (xx)
1470  dalgo = he->p.ui32p[0];
1471  he->p.ptr = _free(he->p.ptr);
1472  }
1473 
1474  switch (dalgo) {
1475  default: dalgo = PGPHASHALGO_MD5; fi->digestlen = 128/8; break;
1476  case PGPHASHALGO_MD2: fi->digestlen = 128/8; break;
1477  case PGPHASHALGO_MD5: fi->digestlen = 128/8; break;
1478  case PGPHASHALGO_SHA1: fi->digestlen = 160/8; break;
1479  case PGPHASHALGO_RIPEMD128: fi->digestlen = 128/8; break;
1480  case PGPHASHALGO_RIPEMD160: fi->digestlen = 160/8; break;
1481  case PGPHASHALGO_RIPEMD256: fi->digestlen = 256/8; break;
1482  case PGPHASHALGO_RIPEMD320: fi->digestlen = 320/8; break;
1483  case PGPHASHALGO_SHA224: fi->digestlen = 224/8; break;
1484  case PGPHASHALGO_SHA256: fi->digestlen = 256/8; break;
1485  case PGPHASHALGO_SHA384: fi->digestlen = 384/8; break;
1486  case PGPHASHALGO_SHA512: fi->digestlen = 512/8; break;
1487  case PGPHASHALGO_CRC32: fi->digestlen = 32/8; break;
1488  }
1489  fi->digestalgo = dalgo;
1490 
1491  fi->digests = NULL;
1492  _fdupedata(h, RPMTAG_FILEDIGESTS, fi->fdigests);
1493  if (fi->fdigests) {
1494  t = xmalloc(fi->fc * fi->digestlen);
1495  fi->digests = t;
1496  for (i = 0; i < (int)fi->fc; i++) {
1497  const char * fdigests;
1498  int j;
1499 
1500  fdigests = fi->fdigests[i];
1501  if (!(fdigests && *fdigests != '\0')) {
1502  memset(t, 0, fi->digestlen);
1503  t += fi->digestlen;
1504  continue;
1505  }
1506  for (j = 0; j < (int)fi->digestlen; j++, t++, fdigests += 2)
1507  *t = (nibble(fdigests[0]) << 4) | nibble(fdigests[1]);
1508  }
1509  fi->fdigests = _free(fi->fdigests);
1510  }
1511 
1512  /* XXX TR_REMOVED doesn't need fmtimes, frdevs, finodes, or fcontexts */
1513  _fdupedata(h, RPMTAG_FILEMTIMES, fi->fmtimes);
1514  _fdupedata(h, RPMTAG_FILERDEVS, fi->frdevs);
1515  _fdupedata(h, RPMTAG_FILEINODES, fi->finodes);
1516  _fdupedata(h, RPMTAG_FILECONTEXTS, fi->fcontexts);
1517 
1518  fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
1519 
1520  _fdupedata(h, RPMTAG_FILEUSERNAME, fi->fuser);
1521  _fdupedata(h, RPMTAG_FILEGROUPNAME, fi->fgroup);
1522 
1523  if (ts != NULL)
1524  if (fi != NULL)
1525  if ((p = rpmtsRelocateElement(ts)) != NULL && rpmteType(p) == TR_ADDED
1528  {
1529  const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL);
1530  const char * errstr;
1531  char * newPath;
1532  Header foo;
1533 
1534  /* XXX error handling. */
1535  newPath = headerSprintf(h, fmt, NULL, rpmHeaderFormats, &errstr);
1536  fmt = _free(fmt);
1537 
1538  /* XXX Make sure autoreloc is not already specified. */
1539  i = p->nrelocs;
1540  if (newPath != NULL && *newPath != '\0' && p->relocs != NULL)
1541  for (i = 0; i < p->nrelocs; i++) {
1542 /*@-nullpass@*/ /* XXX {old,new}Path might be NULL */
1543  if (strcmp(p->relocs[i].oldPath, "/"))
1544  continue;
1545  if (strcmp(p->relocs[i].newPath, newPath))
1546  continue;
1547 /*@=nullpass@*/
1548  break;
1549  }
1550 
1551  /* XXX test for incompatible arch triggering autorelocation is dumb. */
1552  /* XXX DIEDIEDIE: used to test '... && p->archScore == 0' */
1553  if (newPath != NULL && *newPath != '\0' && i == p->nrelocs) {
1554 
1555  p->relocs =
1556  xrealloc(p->relocs, (p->nrelocs + 2) * sizeof(*p->relocs));
1557  p->relocs[p->nrelocs].oldPath = xstrdup("/");
1558  p->relocs[p->nrelocs].newPath = xstrdup(newPath);
1559  p->autorelocatex = p->nrelocs;
1560  p->nrelocs++;
1561  p->relocs[p->nrelocs].oldPath = NULL;
1562  p->relocs[p->nrelocs].newPath = NULL;
1563  }
1564  newPath = _free(newPath);
1565 
1566 /* XXX DYING */
1567 if (fi->actions == NULL)
1568  fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
1569  /*@-compdef@*/ /* FIX: fi->digests undefined */
1570  foo = relocateFileList(ts, fi, h, (iosmFileAction *) fi->actions);
1571  /*@=compdef@*/
1572  (void)headerFree(fi->h);
1573  fi->h = NULL;
1574  fi->h = headerLink(foo);
1575  (void)headerFree(foo);
1576  foo = NULL;
1577  }
1578 
1579  if (fi->isSource && fi->dc == 1 && *fi->dnl[0] == '\0') {
1580  const char ** av = xcalloc(4+1, sizeof(*av));
1581  char * te;
1582  size_t nb;
1583 
1584  xx = headerMacrosLoad(h);
1585  av[0] = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", "");
1586  av[1] = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", "");
1587  av[2] = rpmGenPath(rpmtsRootDir(ts), "%{_patchdir}", "");
1588  av[3] = rpmGenPath(rpmtsRootDir(ts), "%{_icondir}", "");
1589  av[4] = NULL;
1590  xx = headerMacrosUnload(h);
1591 
1592  /* Hack up a header RPM_STRING_ARRAY_TYPE array. */
1593  fi->dnl = _free(fi->dnl);
1594  fi->dc = 4;
1595  nb = fi->dc * sizeof(*av);
1596  for (i = 0; i < (int)fi->dc; i++)
1597  nb += strlen(av[i]) + sizeof("/");
1598 
1599  fi->dnl = xmalloc(nb);
1600  te = (char *) (&fi->dnl[fi->dc]);
1601  *te = '\0';
1602  for (i = 0; i < (int)fi->dc; i++) {
1603  fi->dnl[i] = te;
1604  te = stpcpy( stpcpy(te, av[i]), "/");
1605  *te++ = '\0';
1606  }
1607  av = argvFree(av);
1608 
1609  /* Map basenames to appropriate directories. */
1610  for (i = 0; i < (int)fi->fc; i++) {
1611  if (fi->fflags[i] & RPMFILE_SOURCE)
1612  fi->dil[i] = 0;
1613  else if (fi->fflags[i] & RPMFILE_SPECFILE)
1614  fi->dil[i] = 1;
1615  else if (fi->fflags[i] & RPMFILE_PATCH)
1616  fi->dil[i] = 2;
1617  else if (fi->fflags[i] & RPMFILE_ICON)
1618  fi->dil[i] = 3;
1619  else {
1620  const char * b = fi->bnl[i];
1621  const char * be = b + strlen(b) - sizeof(".spec") - 1;
1622 
1623  fi->dil[i] = (be > b && !strcmp(be, ".spec") ? 1 : 0);
1624  }
1625  }
1626  }
1627 
1628  if (!scareMem)
1629  (void)headerFree(fi->h);
1630  fi->h = NULL;
1631 
1632  fi->fn = NULL;
1633  fi->fnlen = 0;
1634  for (i = 0; i < (int)fi->fc; i++) {
1635  size_t fnlen = strlen(fi->dnl[fi->dil[i]]) + strlen(fi->bnl[i]);
1636  if (fnlen > fi->fnlen)
1637  fi->fnlen = fnlen;
1638  }
1639 
1640  fi->dperms = 0755;
1641  fi->fperms = 0644;
1642 
1643 exit:
1644 /*@-modfilesys@*/
1645 if (_rpmfi_debug < 0)
1646 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, Type, (fi ? fi->fc : 0));
1647 /*@=modfilesys@*/
1648 
1649  /*@-compdef -nullstate@*/ /* FIX: rpmfi null annotations */
1650  return rpmfiLink(fi, (fi ? fi->Type : NULL));
1651  /*@=compdef =nullstate@*/
1652 }
1653 
1654 int rpmfiAddRelocation(rpmRelocation * relp, int * nrelp,
1655  const char * oldPath, const char * newPath)
1656 {
1657 /*@-unqualifiedtrans@*/
1658  *relp = xrealloc(*relp, sizeof(**relp) * ((*nrelp) + 1));
1659 /*@=unqualifiedtrans@*/
1660  (*relp)[*nrelp].oldPath = (oldPath ? xstrdup(oldPath) : NULL);
1661  (*relp)[*nrelp].newPath = (newPath ? xstrdup(newPath) : NULL);
1662  (*nrelp)++;
1663  return 0;
1664 }
1665 
1667 {
1668  if (relocs) {
1669  rpmRelocation r;
1670  for (r = relocs; (r->oldPath || r->newPath); r++) {
1671  r->oldPath = _free(r->oldPath);
1672  r->newPath = _free(r->newPath);
1673  }
1674  relocs = _free(relocs);
1675  }
1676  return NULL;
1677 }
1678 
1680 {
1681  rpmRelocation newr = NULL;
1682  int nrelocs = 0;
1683 
1684  if (relocs) {
1685  rpmRelocation r;
1686  int i;
1687 
1688  for (r = relocs; r->oldPath || r->newPath; r++)
1689  nrelocs++;
1690  newr = xmalloc((nrelocs + 1) * sizeof(*relocs));
1691 
1692  for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
1693  newr[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
1694  newr[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
1695  }
1696  newr[i].oldPath = NULL;
1697  newr[i].newPath = NULL;
1698  }
1699  if (nrelocsp)
1700  *nrelocsp = nrelocs;
1701  return newr;
1702 }
1703 
1704 int rpmfiFStat(rpmfi fi, struct stat * st)
1705 {
1706  int rc = -1;
1707 
1708  if (st != NULL && fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) {
1709  memset(st, 0, sizeof(*st));
1710  st->st_dev =
1711  st->st_rdev = fi->frdevs[fi->i];
1712  st->st_ino = fi->finodes[fi->i];
1713  st->st_mode = fi->fmodes[fi->i];
1714  st->st_nlink = rpmfiFNlink(fi) + (int)S_ISDIR(st->st_mode);
1715  if (unameToUid(fi->fuser[fi->i], &st->st_uid) == -1)
1716  st->st_uid = 0; /* XXX */
1717  if (gnameToGid(fi->fgroup[fi->i], &st->st_gid) == -1)
1718  st->st_gid = 0; /* XXX */
1719  st->st_size = fi->fsizes[fi->i];
1720  st->st_blksize = 4 * 1024; /* XXX */
1721  st->st_blocks = (st->st_size + (st->st_blksize - 1)) / st->st_blksize;
1722  st->st_atime =
1723  st->st_ctime =
1724  st->st_mtime = fi->fmtimes[fi->i];
1725  rc = 0;
1726  }
1727 
1728  return rc;
1729 }
1730 
1731 int rpmfiStat(rpmfi fi, const char * path, struct stat * st)
1732 {
1733  size_t pathlen = strlen(path);
1734  int rc = -1;
1735  int i;
1736 
1737  while (pathlen > 0 && path[pathlen-1] == '/')
1738  pathlen--;
1739 
1740  /* If not actively iterating, initialize. */
1741  if (!(fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc))
1742  fi = rpmfiInit(fi, 0);
1743 
1744  while ((i = rpmfiNext(fi)) >= 0) {
1745  const char * fn = rpmfiFN(fi);
1746  size_t fnlen = strlen(fn);
1747 
1748  if (pathlen != fnlen || strncmp(path, fn, fnlen))
1749  continue;
1750  rc = rpmfiFStat(fi, st);
1751  break;
1752  }
1753 
1754 /*@-modfilesys@*/
1755 if (_rpmfi_debug)
1756 fprintf(stderr, "*** rpmfiStat(%p, %s, %p) rc %d\n", fi, path, st, rc);
1757 /*@=modfilesys@*/
1758 
1759  return rc;
1760 }
1761 
1762 DIR * rpmfiOpendir(rpmfi fi, const char * name)
1763 {
1764  const char * dn = name;
1765  size_t dnlen = strlen(dn);
1766  const char ** fnames = NULL;
1767  rpmuint16_t * fmodes = NULL;
1768  DIR * dir;
1769  int xx;
1770  int i, j;
1771 
1772  j = 0;
1773  fmodes = xcalloc(fi->fc, sizeof(*fmodes));
1774 
1775  /* XXX todo full iteration is pig slow, fi->dil can be used for speedup. */
1776  fi = rpmfiInit(fi, 0);
1777  while ((i = rpmfiNext(fi)) >= 0) {
1778  const char * fn = rpmfiFN(fi);
1779  size_t fnlen = strlen(fn);
1780 
1781  if (fnlen <= dnlen)
1782  continue;
1783  if (strncmp(dn, fn, dnlen) || fn[dnlen] != '/')
1784  continue;
1785 
1786  /* XXX todo basename, or orphandir/.../basname, needs to be used. */
1787  /* Trim the directory part of the name. */
1788  xx = argvAdd(&fnames, fn + dnlen + 1);
1789  fmodes[j++] = fi->fmodes[i];
1790  }
1791 
1792  /* Add "." & ".." to the argv array. */
1793  dir = (DIR *) avOpendir(name, fnames, fmodes);
1794 
1795  fnames = argvFree(fnames);
1796  fmodes = _free(fmodes);
1797 
1798 /*@-modfilesys +voidabstract @*/
1799 if (_rpmfi_debug)
1800 fprintf(stderr, "*** rpmfiOpendir(%p, %s) dir %p\n", fi, name, dir);
1801 /*@=modfilesys =voidabstract @*/
1802 
1803  return dir;
1804 }
1805 
1807  /*@out@*/ const char *** fclassp, /*@out@*/ rpmuint32_t * fcp)
1808 {
1809  int scareMem = 0;
1810  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1811  const char * FClass;
1812  const char ** av;
1813  int ac;
1814  size_t nb;
1815  char * t;
1816 
1817  if ((ac = rpmfiFC(fi)) <= 0) {
1818  av = NULL;
1819  ac = 0;
1820  goto exit;
1821  }
1822 
1823  /* Compute size of file class argv array blob. */
1824  nb = (ac + 1) * sizeof(*av);
1825  fi = rpmfiInit(fi, 0);
1826  if (fi != NULL)
1827  while (rpmfiNext(fi) >= 0) {
1828  FClass = rpmfiFClass(fi);
1829  if (FClass && *FClass != '\0')
1830  nb += strlen(FClass);
1831  nb += 1;
1832  }
1833 
1834  /* Create and load file class argv array. */
1835  av = xmalloc(nb);
1836  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1837  ac = 0;
1838  fi = rpmfiInit(fi, 0);
1839  if (fi != NULL)
1840  while (rpmfiNext(fi) >= 0) {
1841  FClass = rpmfiFClass(fi);
1842  av[ac++] = t;
1843  if (FClass && *FClass != '\0')
1844  t = stpcpy(t, FClass);
1845  *t++ = '\0';
1846  }
1847  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1848 
1849 exit:
1850  fi = rpmfiFree(fi);
1851  if (fclassp)
1852  *fclassp = av;
1853  else
1854  av = _free(av);
1855  if (fcp) *fcp = ac;
1856 }
1857 
1859  /*@out@*/ const char *** fcontextp, /*@out@*/ rpmuint32_t * fcp)
1860 {
1861  int scareMem = 0;
1862  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1863  const char * fcontext;
1864  const char ** av;
1865  int ac;
1866  size_t nb;
1867  char * t;
1868 
1869  if ((ac = rpmfiFC(fi)) <= 0) {
1870  av = NULL;
1871  ac = 0;
1872  goto exit;
1873  }
1874 
1875  /* Compute size of argv array blob. */
1876  nb = (ac + 1) * sizeof(*av);
1877  fi = rpmfiInit(fi, 0);
1878  if (fi != NULL)
1879  while (rpmfiNext(fi) >= 0) {
1880  fcontext = rpmfiFContext(fi);
1881  if (fcontext && *fcontext != '\0')
1882  nb += strlen(fcontext);
1883  nb += 1;
1884  }
1885 
1886  /* Create and load argv array. */
1887  av = xmalloc(nb);
1888  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1889  ac = 0;
1890  fi = rpmfiInit(fi, 0);
1891  if (fi != NULL)
1892  while (rpmfiNext(fi) >= 0) {
1893  fcontext = rpmfiFContext(fi);
1894  av[ac++] = t;
1895  if (fcontext && *fcontext != '\0')
1896  t = stpcpy(t, fcontext);
1897  *t++ = '\0';
1898  }
1899  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1900 
1901 exit:
1902  fi = rpmfiFree(fi);
1903  if (fcontextp)
1904  *fcontextp = av;
1905  else
1906  av = _free(av);
1907  if (fcp) *fcp = ac;
1908 }
1909 
1911  /*@out@*/ const char *** fcontextp, /*@out@*/ rpmuint32_t * fcp)
1912 {
1913  int scareMem = 0;
1914  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1915  const char ** av;
1916  int ac;
1917  size_t nb;
1918  char * t;
1919  char * fctxt = NULL;
1920  size_t fctxtlen = 0;
1921  int * fcnb;
1922 
1923  if ((ac = rpmfiFC(fi)) <= 0) {
1924  av = NULL;
1925  ac = 0;
1926  goto exit;
1927  }
1928 
1929  /* Compute size of argv array blob, concatenating file contexts. */
1930  nb = ac * sizeof(*fcnb);
1931  fcnb = memset(alloca(nb), 0, nb);
1932  ac = 0;
1933  fi = rpmfiInit(fi, 0);
1934  if (fi != NULL)
1935  while (rpmfiNext(fi) >= 0) {
1936  const char *fn;
1937  security_context_t scon = NULL;
1938 
1939  fn = rpmfiFN(fi);
1940  fcnb[ac] = lgetfilecon(fn, &scon);
1941  if (fcnb[ac] > 0) {
1942  fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
1943  memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
1944  fctxtlen += fcnb[ac];
1945  freecon(scon);
1946  }
1947  ac++;
1948  }
1949 
1950  /* Create and load argv array from concatenated file contexts. */
1951  nb = (ac + 1) * sizeof(*av) + fctxtlen;
1952  av = xmalloc(nb);
1953  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1954  if (fctxt != NULL && fctxtlen > 0)
1955  (void) memcpy(t, fctxt, fctxtlen);
1956  ac = 0;
1957  fi = rpmfiInit(fi, 0);
1958  if (fi != NULL)
1959  while (rpmfiNext(fi) >= 0) {
1960  av[ac] = "";
1961  if (fcnb[ac] > 0) {
1962  av[ac] = t;
1963  t += fcnb[ac];
1964  }
1965  ac++;
1966  }
1967  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1968 
1969 exit:
1970  fi = rpmfiFree(fi);
1971  if (fcontextp)
1972  *fcontextp = av;
1973  else
1974  av = _free(av);
1975  if (fcp) *fcp = ac;
1976 }
1977 
1979  /*@out@*/ const char *** fcontextp, /*@out@*/ rpmuint32_t * fcp)
1980 {
1981  int scareMem = 0;
1982  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1983  const char ** av = NULL;
1984  int ac;
1985  size_t nb;
1986  char * t;
1987  char * fctxt = NULL;
1988  size_t fctxtlen = 0;
1989  int * fcnb;
1990 
1991  if ((ac = rpmfiFC(fi)) <= 0) {
1992  ac = 0;
1993  goto exit;
1994  }
1995 
1996  /* Read security context patterns. */
1997  { const char *fn = rpmGetPath("%{?__file_context_path}", NULL);
1998 /*@-moduncon -noeffectuncon @*/
1999  if (fn != NULL && *fn != '\0')
2000  (void)matchpathcon_init(fn);
2001 /*@=moduncon =noeffectuncon @*/
2002  fn = _free(fn);
2003  }
2004 
2005  /* Compute size of argv array blob, concatenating file contexts. */
2006  nb = ac * sizeof(*fcnb);
2007  fcnb = memset(alloca(nb), 0, nb);
2008  ac = 0;
2009  fi = rpmfiInit(fi, 0);
2010  if (fi != NULL)
2011  while (rpmfiNext(fi) >= 0) {
2012  const char *fn;
2013  mode_t fmode;
2014  security_context_t scon;
2015 
2016  fn = rpmfiFN(fi);
2017  fmode = rpmfiFMode(fi);
2018  scon = NULL;
2019 /*@-moduncon@*/
2020  if (matchpathcon(fn, fmode, &scon) == 0 && scon != NULL) {
2021  fcnb[ac] = strlen(scon) + 1;
2022  if (fcnb[ac] > 0) {
2023  fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
2024  memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
2025  fctxtlen += fcnb[ac];
2026  }
2027  freecon(scon);
2028  }
2029 /*@=moduncon@*/
2030  ac++;
2031  }
2032 
2033  /* Create and load argv array from concatenated file contexts. */
2034  nb = (ac + 1) * sizeof(*av) + fctxtlen;
2035  av = xmalloc(nb);
2036  t = ((char *) av) + ((ac + 1) * sizeof(*av));
2037  (void) memcpy(t, fctxt, fctxtlen);
2038  ac = 0;
2039  fi = rpmfiInit(fi, 0);
2040  if (fi != NULL)
2041  while (rpmfiNext(fi) >= 0) {
2042  av[ac] = "";
2043  if (fcnb[ac] > 0) {
2044  av[ac] = t;
2045  t += fcnb[ac];
2046  }
2047  ac++;
2048  }
2049  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
2050 
2051 exit:
2052 /*@-moduncon -noeffectuncon @*/
2054 /*@=moduncon =noeffectuncon @*/
2055  fi = rpmfiFree(fi);
2056  if (fcontextp)
2057  *fcontextp = av;
2058  else
2059  av = _free(av);
2060  if (fcp) *fcp = ac;
2061 }
2062 
2064  /*@out@*/ const char *** fdepsp, /*@out@*/ rpmuint32_t * fcp)
2065 {
2066  int scareMem = 0;
2067  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
2068  rpmds ds = NULL;
2069  const char ** av;
2070  int ac;
2071  size_t nb;
2072  char * t;
2073  char deptype = 'R';
2074  char mydt;
2075  const char * DNEVR;
2076  const rpmuint32_t * ddict;
2077  unsigned ix;
2078  int ndx;
2079 
2080  if ((ac = rpmfiFC(fi)) <= 0) {
2081  av = NULL;
2082  ac = 0;
2083  goto exit;
2084  }
2085 
2086  if (tagN == RPMTAG_PROVIDENAME)
2087  deptype = 'P';
2088  else if (tagN == RPMTAG_REQUIRENAME)
2089  deptype = 'R';
2090 
2091  ds = rpmdsNew(h, tagN, scareMem);
2092 
2093  /* Compute size of file depends argv array blob. */
2094  nb = (ac + 1) * sizeof(*av);
2095  fi = rpmfiInit(fi, 0);
2096  if (fi != NULL)
2097  while (rpmfiNext(fi) >= 0) {
2098  ddict = NULL;
2099  ndx = rpmfiFDepends(fi, &ddict);
2100  if (ddict != NULL)
2101  while (ndx-- > 0) {
2102  ix = *ddict++;
2103  mydt = ((ix >> 24) & 0xff);
2104  if (mydt != deptype)
2105  /*@innercontinue@*/ continue;
2106  ix &= 0x00ffffff;
2107  (void) rpmdsSetIx(ds, ix-1);
2108  if (rpmdsNext(ds) < 0)
2109  /*@innercontinue@*/ continue;
2110  DNEVR = rpmdsDNEVR(ds);
2111  if (DNEVR != NULL)
2112  nb += strlen(DNEVR+2) + 1;
2113  }
2114  nb += 1;
2115  }
2116 
2117  /* Create and load file depends argv array. */
2118  av = xmalloc(nb);
2119  t = ((char *) av) + ((ac + 1) * sizeof(*av));
2120  ac = 0;
2121  fi = rpmfiInit(fi, 0);
2122  if (fi != NULL)
2123  while (rpmfiNext(fi) >= 0) {
2124  av[ac++] = t;
2125  ddict = NULL;
2126  ndx = rpmfiFDepends(fi, &ddict);
2127  if (ddict != NULL)
2128  while (ndx-- > 0) {
2129  ix = *ddict++;
2130  mydt = ((ix >> 24) & 0xff);
2131  if (mydt != deptype)
2132  /*@innercontinue@*/ continue;
2133  ix &= 0x00ffffff;
2134  (void) rpmdsSetIx(ds, ix-1);
2135  if (rpmdsNext(ds) < 0)
2136  /*@innercontinue@*/ continue;
2137  DNEVR = rpmdsDNEVR(ds);
2138  if (DNEVR != NULL) {
2139  t = stpcpy(t, DNEVR+2);
2140  *t++ = ' ';
2141  *t = '\0';
2142  }
2143  }
2144  *t++ = '\0';
2145  }
2146  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
2147 
2148 exit:
2149  fi = rpmfiFree(fi);
2150  (void)rpmdsFree(ds);
2151  ds = NULL;
2152  if (fdepsp)
2153  *fdepsp = av;
2154  else
2155  av = _free(av);
2156  if (fcp) *fcp = ac;
2157 }