rpm  4.5
rpmfi.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h>
9 #include <rpmlib.h>
10 
11 #include "cpio.h" /* XXX CPIO_FOO */
12 #include "fsm.h" /* XXX newFSM() */
13 
14 #include "rpmds.h"
15 
16 #include "legacy.h"
17 
18 #define _RPMFI_INTERNAL
19 #include "rpmfi.h"
20 
21 #define _RPMTE_INTERNAL /* relocations */
22 #include "rpmte.h"
23 #include "rpmts.h"
24 
25 #include "misc.h" /* XXX stripTrailingChar */
26 #include "rpmmacro.h" /* XXX rpmCleanPath */
27 
28 #include "debug.h"
29 
30 /*@access rpmte @*/
31 /*@access FSM_t @*/ /* XXX fsm->repackaged */
32 
33 /*@unchecked@*/
34 int _rpmfi_debug = 0;
35 
36 rpmfi XrpmfiUnlink(rpmfi fi, const char * msg, const char * fn, unsigned ln)
37 {
38  if (fi == NULL) return NULL;
39 /*@-modfilesys@*/
40 if (_rpmfi_debug && msg != NULL)
41 fprintf(stderr, "--> fi %p -- %d %s at %s:%u\n", fi, fi->nrefs, msg, fn, ln);
42 /*@=modfilesys@*/
43  fi->nrefs--;
44  return NULL;
45 }
46 
47 rpmfi XrpmfiLink(rpmfi fi, const char * msg, const char * fn, unsigned ln)
48 {
49  if (fi == NULL) return NULL;
50  fi->nrefs++;
51 /*@-modfilesys@*/
52 if (_rpmfi_debug && msg != NULL)
53 fprintf(stderr, "--> fi %p ++ %d %s at %s:%u\n", fi, fi->nrefs, msg, fn, ln);
54 /*@=modfilesys@*/
55  /*@-refcounttrans@*/ return fi; /*@=refcounttrans@*/
56 }
57 
58 int rpmfiFC(rpmfi fi)
59 {
60  return (fi != NULL ? fi->fc : 0);
61 }
62 
63 int rpmfiDC(rpmfi fi)
64 {
65  return (fi != NULL ? fi->dc : 0);
66 }
67 
68 #ifdef NOTYET
69 int rpmfiDI(rpmfi fi)
70 {
71 }
72 #endif
73 
74 int rpmfiFX(rpmfi fi)
75 {
76  return (fi != NULL ? fi->i : -1);
77 }
78 
79 int rpmfiSetFX(rpmfi fi, int fx)
80 {
81  int i = -1;
82 
83  if (fi != NULL && fx >= 0 && fx < fi->fc) {
84  i = fi->i;
85  fi->i = fx;
86 /*@-boundsread@*/
87  fi->j = fi->dil[fi->i];
88 /*@=boundsread@*/
89  }
90  return i;
91 }
92 
93 int rpmfiDX(rpmfi fi)
94 {
95  return (fi != NULL ? fi->j : -1);
96 }
97 
98 int rpmfiSetDX(rpmfi fi, int dx)
99 {
100  int j = -1;
101 
102  if (fi != NULL && dx >= 0 && dx < fi->dc) {
103  j = fi->j;
104  fi->j = dx;
105  }
106  return j;
107 }
108 
109 const char * rpmfiBN(rpmfi fi)
110 {
111  const char * BN = NULL;
112 
113  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
114 /*@-boundsread@*/
115  if (fi->bnl != NULL)
116  BN = fi->bnl[fi->i];
117 /*@=boundsread@*/
118  }
119  return BN;
120 }
121 
122 const char * rpmfiDN(rpmfi fi)
123 {
124  const char * DN = NULL;
125 
126  if (fi != NULL && fi->j >= 0 && fi->j < fi->dc) {
127 /*@-boundsread@*/
128  if (fi->dnl != NULL)
129  DN = fi->dnl[fi->j];
130 /*@=boundsread@*/
131  }
132  return DN;
133 }
134 
135 const char * rpmfiFN(rpmfi fi)
136 {
137  const char * FN = "";
138 
139  /*@-branchstate@*/
140  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
141  const char *dn;
142  char * t;
143  if (fi->fn == NULL)
144  fi->fn = xmalloc(fi->fnlen);
145  FN = t = fi->fn;
146  (void) urlPath(fi->dnl[fi->dil[fi->i]], &dn);
147 /*@-boundswrite@*/
148  *t = '\0';
149  t = stpcpy(t, dn);
150  t = stpcpy(t, fi->bnl[fi->i]);
151 /*@=boundswrite@*/
152  }
153  /*@=branchstate@*/
154  return FN;
155 }
156 
158 {
159  uint_32 FFlags = 0;
160 
161  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
162 /*@-boundsread@*/
163  if (fi->fflags != NULL)
164  FFlags = fi->fflags[fi->i];
165 /*@=boundsread@*/
166  }
167  return FFlags;
168 }
169 
171 {
172  uint_32 oFFlags = 0;
173 
174  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
175 /*@-boundsread@*/
176  if (fi->fflags != NULL && fi->h == NULL) {
177  oFFlags = fi->fflags[fi->i];
178  *((uint_32 *)(fi->fflags + fi->i)) = FFlags;
179  }
180 /*@=boundsread@*/
181  }
182  return oFFlags;
183 }
184 
186 {
187  uint_32 VFlags = 0;
188 
189  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
190 /*@-boundsread@*/
191  if (fi->vflags != NULL)
192  VFlags = fi->vflags[fi->i];
193 /*@=boundsread@*/
194  }
195  return VFlags;
196 }
197 
199 {
200  uint_32 oVFlags = 0;
201 
202  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
203 /*@-boundsread@*/
204  if (fi->vflags != NULL && fi->h == NULL) {
205  oVFlags = fi->vflags[fi->i];
206  *((uint_32 *)(fi->vflags + fi->i)) = VFlags;
207  }
208 /*@=boundsread@*/
209  }
210  return oVFlags;
211 }
212 
214 {
215  int_16 fmode = 0;
216 
217  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
218 /*@-boundsread@*/
219  if (fi->fmodes != NULL)
220  fmode = fi->fmodes[fi->i];
221 /*@=boundsread@*/
222  }
223  return fmode;
224 }
225 
227 {
229 
230  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
231 /*@-boundsread@*/
232  if (fi->fstates != NULL)
233  fstate = fi->fstates[fi->i];
234 /*@=boundsread@*/
235  }
236  return fstate;
237 }
238 
240 {
241  int_32 ofstate = 0;
242 
243  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
244 /*@-boundsread@*/
245  if (fi->fstates != NULL) {
246  ofstate = fi->fstates[fi->i];
247  fi->fstates[fi->i] = fstate;
248  }
249 /*@=boundsread@*/
250  }
251  return ofstate;
252 }
253 
254 const unsigned char * rpmfiDigest(rpmfi fi, int * algop, size_t * lenp)
255 {
256  unsigned char * digest = NULL;
257 
258  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
259 /*@-boundsread@*/
260  if (fi->digests != NULL) {
261  digest = fi->digests + (fi->digestlen * fi->i);
262  if (algop != NULL)
263  *algop = (fi->fdigestalgos
264  ? fi->fdigestalgos[fi->i] : fi->digestalgo);
265  if (lenp != NULL)
266  *lenp = fi->digestlen;
267  }
268 /*@=boundsread@*/
269  }
270  return digest;
271 }
272 
273 const char * rpmfiFLink(rpmfi fi)
274 {
275  const char * flink = NULL;
276 
277  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
278 /*@-boundsread@*/
279  if (fi->flinks != NULL)
280  flink = fi->flinks[fi->i];
281 /*@=boundsread@*/
282  }
283  return flink;
284 }
285 
287 {
288  int_32 fsize = 0;
289 
290  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
291 /*@-boundsread@*/
292  if (fi->fsizes != NULL)
293  fsize = fi->fsizes[fi->i];
294 /*@=boundsread@*/
295  }
296  return fsize;
297 }
298 
300 {
301  int_16 frdev = 0;
302 
303  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
304 /*@-boundsread@*/
305  if (fi->frdevs != NULL)
306  frdev = fi->frdevs[fi->i];
307 /*@=boundsread@*/
308  }
309  return frdev;
310 }
311 
313 {
314  int_32 finode = 0;
315 
316  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
317 /*@-boundsread@*/
318  if (fi->finodes != NULL)
319  finode = fi->finodes[fi->i];
320 /*@=boundsread@*/
321  }
322  return finode;
323 }
324 
326 {
327  uint_32 color = 0;
328 
329  if (fi != NULL)
330  /* XXX ignore all but lsnibble for now. */
331  color = fi->color & 0xf;
332  return color;
333 }
334 
336 {
337  uint_32 fcolor = 0;
338 
339  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
340 /*@-boundsread@*/
341  if (fi->fcolors != NULL)
342  /* XXX ignore all but lsnibble for now. */
343  fcolor = (fi->fcolors[fi->i] & 0x0f);
344 /*@=boundsread@*/
345  }
346  return fcolor;
347 }
348 
349 const char * rpmfiFClass(rpmfi fi)
350 {
351  const char * fclass = NULL;
352  int cdictx;
353 
354  if (fi != NULL && fi->fcdictx != NULL && fi->i >= 0 && fi->i < fi->fc) {
355 /*@-boundsread@*/
356  cdictx = fi->fcdictx[fi->i];
357  if (fi->cdict != NULL && cdictx >= 0 && cdictx < fi->ncdict)
358  fclass = fi->cdict[cdictx];
359 /*@=boundsread@*/
360  }
361  return fclass;
362 }
363 
364 const char * rpmfiFContext(rpmfi fi)
365 {
366  const char * fcontext = NULL;
367 
368  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
369 /*@-boundsread@*/
370  if (fi->fcontexts != NULL)
371  fcontext = fi->fcontexts[fi->i];
372 /*@=boundsread@*/
373  }
374  return fcontext;
375 }
376 
377 int_32 rpmfiFDepends(rpmfi fi, const uint_32 ** fddictp)
378 {
379  int fddictx = -1;
380  int fddictn = 0;
381  const uint_32 * fddict = NULL;
382 
383  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
384 /*@-boundsread@*/
385  if (fi->fddictn != NULL)
386  fddictn = fi->fddictn[fi->i];
387  if (fddictn > 0 && fi->fddictx != NULL)
388  fddictx = fi->fddictx[fi->i];
389  if (fi->ddict != NULL && fddictx >= 0 && (fddictx+fddictn) <= fi->nddict)
390  fddict = fi->ddict + fddictx;
391 /*@=boundsread@*/
392  }
393 /*@-boundswrite -dependenttrans -onlytrans @*/
394  if (fddictp)
395  *fddictp = fddict;
396 /*@=boundswrite =dependenttrans =onlytrans @*/
397  return fddictn;
398 }
399 
401 {
402  int_32 nlink = 0;
403 
404  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
405  /* XXX rpm-2.3.12 has not RPMTAG_FILEINODES */
406 /*@-boundsread@*/
407  if (fi->finodes && fi->frdevs) {
408  int_32 finode = fi->finodes[fi->i];
409  int_16 frdev = fi->frdevs[fi->i];
410  int j;
411 
412  for (j = 0; j < fi->fc; j++) {
413  if (fi->frdevs[j] == frdev && fi->finodes[j] == finode)
414  nlink++;
415  }
416  }
417 /*@=boundsread@*/
418  }
419  return nlink;
420 }
421 
423 {
424  int_32 fmtime = 0;
425 
426  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
427 /*@-boundsread@*/
428  if (fi->fmtimes != NULL)
429  fmtime = fi->fmtimes[fi->i];
430 /*@=boundsread@*/
431  }
432  return fmtime;
433 }
434 
435 const char * rpmfiFUser(rpmfi fi)
436 {
437  const char * fuser = NULL;
438 
439  /* XXX add support for ancient RPMTAG_FILEUIDS? */
440  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
441 /*@-boundsread@*/
442  if (fi->fuser != NULL)
443  fuser = fi->fuser[fi->i];
444 /*@=boundsread@*/
445  }
446  return fuser;
447 }
448 
449 const char * rpmfiFGroup(rpmfi fi)
450 {
451  const char * fgroup = NULL;
452 
453  /* XXX add support for ancient RPMTAG_FILEGIDS? */
454  if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
455 /*@-boundsread@*/
456  if (fi->fgroup != NULL)
457  fgroup = fi->fgroup[fi->i];
458 /*@=boundsread@*/
459  }
460  return fgroup;
461 }
462 
464 {
465  int i = -1;
466 
467  if (fi != NULL && ++fi->i >= 0) {
468  if (fi->i < fi->fc) {
469  i = fi->i;
470 /*@-boundsread@*/
471  if (fi->dil != NULL)
472  fi->j = fi->dil[fi->i];
473 /*@=boundsread@*/
474  } else
475  fi->i = -1;
476 
477 /*@-modfilesys @*/
478 if (_rpmfi_debug < 0 && i != -1)
479 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] : ""));
480 /*@=modfilesys @*/
481 
482  }
483 
484  return i;
485 }
486 
487 rpmfi rpmfiInit(rpmfi fi, int fx)
488 {
489  if (fi != NULL) {
490  if (fx >= 0 && fx < fi->fc) {
491  fi->i = fx - 1;
492  fi->j = -1;
493  }
494  }
495 
496  /*@-refcounttrans@*/
497  return fi;
498  /*@=refcounttrans@*/
499 }
500 
502 {
503  int j = -1;
504 
505  if (fi != NULL && ++fi->j >= 0) {
506  if (fi->j < fi->dc)
507  j = fi->j;
508  else
509  fi->j = -1;
510 
511 /*@-modfilesys @*/
512 if (_rpmfi_debug < 0 && j != -1)
513 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, (fi->Type ? fi->Type : "?Type?"), j);
514 /*@=modfilesys @*/
515 
516  }
517 
518  return j;
519 }
520 
521 rpmfi rpmfiInitD(rpmfi fi, int dx)
522 {
523  if (fi != NULL) {
524  if (dx >= 0 && dx < fi->fc)
525  fi->j = dx - 1;
526  else
527  fi = NULL;
528  }
529 
530  /*@-refcounttrans@*/
531  return fi;
532  /*@=refcounttrans@*/
533 }
534 
540 static /*@observer@*/
541 const char * ftstring (fileTypes ft)
542  /*@*/
543 {
544  switch (ft) {
545  case XDIR: return "directory";
546  case CDEV: return "char dev";
547  case BDEV: return "block dev";
548  case LINK: return "link";
549  case SOCK: return "sock";
550  case PIPE: return "fifo/pipe";
551  case REG: return "file";
552  default: return "unknown file type";
553  }
554  /*@notreached@*/
555 }
556 
558 {
559  if (S_ISDIR(mode)) return XDIR;
560  if (S_ISCHR(mode)) return CDEV;
561  if (S_ISBLK(mode)) return BDEV;
562  if (S_ISLNK(mode)) return LINK;
563 /*@-unrecog@*/
564  if (S_ISSOCK(mode)) return SOCK;
565 /*@=unrecog@*/
566  if (S_ISFIFO(mode)) return PIPE;
567  return REG;
568 }
569 
570 /*@-boundsread@*/
571 int rpmfiCompare(const rpmfi afi, const rpmfi bfi)
572  /*@*/
573 {
574  fileTypes awhat = whatis(rpmfiFMode(afi));
575  fileTypes bwhat = whatis(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 /*@=boundsread@*/
605 
606 /*@-boundsread@*/
607 fileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
608 {
609  const char * fn = rpmfiFN(nfi);
610  int newFlags = rpmfiFFlags(nfi);
611  char buffer[1024+1];
612  fileTypes dbWhat, newWhat, diskWhat;
613  struct stat sb;
614  int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
615 
616  if (lstat(fn, &sb)) {
617  /*
618  * The file doesn't exist on the disk. Create it unless the new
619  * package has marked it as missingok, or allfiles is requested.
620  */
621  if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) {
622  rpmMessage(RPMMESS_DEBUG, D_("%s skipped due to missingok flag\n"),
623  fn);
624  return FA_SKIP;
625  } else {
626  return FA_CREATE;
627  }
628  }
629 
630  diskWhat = whatis((int_16)sb.st_mode);
631  dbWhat = whatis(rpmfiFMode(ofi));
632  newWhat = whatis(rpmfiFMode(nfi));
633 
634  /*
635  * RPM >= 2.3.10 shouldn't create config directories -- we'll ignore
636  * them in older packages as well.
637  */
638  if (newWhat == XDIR)
639  return FA_CREATE;
640 
641  if (diskWhat != newWhat && dbWhat != REG && dbWhat != LINK)
642  return save;
643  else if (newWhat != dbWhat && diskWhat != dbWhat)
644  return save;
645  else if (dbWhat != newWhat)
646  return FA_CREATE;
647  else if (dbWhat != LINK && dbWhat != REG)
648  return FA_CREATE;
649 
650  /*
651  * This order matters - we'd prefer to CREATE the file if at all
652  * possible in case something else (like the timestamp) has changed.
653  */
654  memset(buffer, 0, sizeof(buffer));
655  if (dbWhat == REG) {
656  int oalgo = 0;
657  size_t olen = 0;
658  const unsigned char * odigest;
659  int nalgo = 0;
660  size_t nlen = 0;
661  const unsigned char * ndigest;
662  odigest = rpmfiDigest(ofi, &oalgo, &olen);
663  if (diskWhat == REG) {
664  if (!(newFlags & RPMFILE_SPARSE))
665  if (dodigest(oalgo, fn, buffer, 0, NULL))
666  return FA_CREATE; /* assume file has been removed */
667  if (odigest && !memcmp(odigest, buffer, olen))
668  return FA_CREATE; /* unmodified config file, replace. */
669  }
670  ndigest = rpmfiDigest(nfi, &nalgo, &nlen);
671 /*@-nullpass@*/
672  if (odigest && ndigest && oalgo == nalgo && olen == nlen
673  && !memcmp(odigest, ndigest, nlen))
674  return FA_SKIP; /* identical file, don't bother. */
675 /*@=nullpass@*/
676  } else /* dbWhat == LINK */ {
677  const char * oFLink, * nFLink;
678  oFLink = rpmfiFLink(ofi);
679  if (diskWhat == LINK) {
680  if (readlink(fn, buffer, sizeof(buffer) - 1) == -1)
681  return FA_CREATE; /* assume file has been removed */
682  buffer[sizeof(buffer)-1] = '\0';
683  if (oFLink && !strcmp(oFLink, buffer))
684  return FA_CREATE; /* unmodified config file, replace. */
685  }
686  nFLink = rpmfiFLink(nfi);
687 /*@-nullpass@*/
688  if (oFLink && nFLink && !strcmp(oFLink, nFLink))
689  return FA_SKIP; /* identical file, don't bother. */
690 /*@=nullpass@*/
691  }
692 
693  /*
694  * The config file on the disk has been modified, but
695  * the ones in the two packages are different. It would
696  * be nice if RPM was smart enough to at least try and
697  * merge the difference ala CVS, but...
698  */
699  return save;
700 }
701 /*@=boundsread@*/
702 
703 /*@observer@*/
704 const char * rpmfiTypeString(rpmfi fi)
705 {
706  switch(rpmteType(fi->te)) {
707  case TR_ADDED: return " install";
708  case TR_REMOVED: return " erase";
709  default: return "???";
710  }
711  /*@noteached@*/
712 }
713 
714 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
715 
725 /*@-bounds@*/
726 static
728  Header origH, fileAction * actions)
729  /*@globals h_errno, rpmGlobalMacroContext @*/
730  /*@modifies ts, fi, origH, actions, rpmGlobalMacroContext @*/
731 {
732  rpmte p = rpmtsRelocateElement(ts);
733  HGE_t hge = fi->hge;
734  HAE_t hae = fi->hae;
735  HME_t hme = fi->hme;
736  HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
737  static int _printed = 0;
738  int allowBadRelocate = (rpmtsFilterFlags(ts) & RPMPROB_FILTER_FORCERELOCATE);
739  rpmRelocation relocations = NULL;
740  int numRelocations;
741  const char ** validRelocations;
742  rpmTagType validType;
743  int numValid;
744  const char ** baseNames;
745  const char ** dirNames;
746  int_32 * dirIndexes;
747  int_32 * newDirIndexes;
748  int_32 fileCount;
749  int_32 dirCount;
750  uint_32 mydColor = rpmExpandNumeric("%{?_autorelocate_dcolor}");
751  uint_32 * fFlags = NULL;
752  uint_32 * fColors = NULL;
753  uint_32 * dColors = NULL;
754  uint_16 * fModes = NULL;
755  Header h;
756  int nrelocated = 0;
757  int fileAlloced = 0;
758  char * fn = NULL;
759  int haveRelocatedFile = 0;
760  int reldel = 0;
761  int len;
762  int i, j, xx;
763 
764  if (!hge(origH, RPMTAG_PREFIXES, &validType, &validRelocations, &numValid))
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  xx = hae(origH, RPMTAG_INSTPREFIXES,
784  validType, validRelocations, numValid);
785  validRelocations = hfd(validRelocations, validType);
786  }
787  /* XXX FIXME multilib file actions need to be checked. */
788  return headerLink(origH);
789  }
790 
791  h = headerLink(origH);
792 
793  relocations = alloca(sizeof(*relocations) * numRelocations);
794 
795  /* Build sorted relocation list from raw relocations. */
796  for (i = 0; i < numRelocations; i++) {
797  char * t;
798 
799  /*
800  * Default relocations (oldPath == NULL) are handled in the UI,
801  * not rpmlib.
802  */
803  if (p->relocs[i].oldPath == NULL) continue; /* XXX can't happen */
804 
805  /* FIXME: Trailing /'s will confuse us greatly. Internal ones will
806  too, but those are more trouble to fix up. :-( */
807  t = alloca_strdup(p->relocs[i].oldPath);
808  /*@-branchstate@*/
809  relocations[i].oldPath = (t[0] == '/' && t[1] == '\0')
810  ? t
811  : stripTrailingChar(t, '/');
812  /*@=branchstate@*/
813 
814  /* An old path w/o a new path is valid, and indicates exclusion */
815  if (p->relocs[i].newPath) {
816  int del;
817 
818  t = alloca_strdup(p->relocs[i].newPath);
819  /*@-branchstate@*/
820  relocations[i].newPath = (t[0] == '/' && t[1] == '\0')
821  ? t
822  : stripTrailingChar(t, '/');
823  /*@=branchstate@*/
824 
825  /*@-nullpass@*/ /* FIX: relocations[i].oldPath == NULL */
826  /* Verify that the relocation's old path is in the header. */
827  for (j = 0; j < numValid; j++) {
828  if (!strcmp(validRelocations[j], relocations[i].oldPath))
829  /*@innerbreak@*/ break;
830  }
831 
832  /* XXX actions check prevents problem from being appended twice. */
833  if (j == numValid && !allowBadRelocate && actions) {
834  rpmps ps = rpmtsProblems(ts);
836  rpmteNEVR(p), rpmteKey(p),
837  relocations[i].oldPath, NULL, NULL, 0);
838  ps = rpmpsFree(ps);
839  }
840  del =
841  strlen(relocations[i].newPath) - strlen(relocations[i].oldPath);
842  /*@=nullpass@*/
843 
844  if (del > reldel)
845  reldel = del;
846  } else {
847  relocations[i].newPath = NULL;
848  }
849  }
850 
851  /* stupid bubble sort, but it's probably faster here */
852  for (i = 0; i < numRelocations; i++) {
853  int madeSwap;
854  madeSwap = 0;
855  for (j = 1; j < numRelocations; j++) {
856  struct rpmRelocation_s tmpReloc;
857  if (relocations[j - 1].oldPath == NULL || /* XXX can't happen */
858  relocations[j ].oldPath == NULL || /* XXX can't happen */
859  strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0)
860  /*@innercontinue@*/ continue;
861  /*@-usereleased@*/ /* LCL: ??? */
862  tmpReloc = relocations[j - 1];
863  relocations[j - 1] = relocations[j];
864  relocations[j] = tmpReloc;
865  /*@=usereleased@*/
866  madeSwap = 1;
867  }
868  if (!madeSwap) break;
869  }
870 
871  if (!_printed) {
872  _printed = 1;
873  rpmMessage(RPMMESS_DEBUG, D_("========== relocations\n"));
874  for (i = 0; i < numRelocations; i++) {
875  if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */
876  if (relocations[i].newPath == NULL)
877  rpmMessage(RPMMESS_DEBUG, D_("%5d exclude %s\n"),
878  i, relocations[i].oldPath);
879  else
880  rpmMessage(RPMMESS_DEBUG, D_("%5d relocate %s -> %s\n"),
881  i, relocations[i].oldPath, relocations[i].newPath);
882  }
883  }
884 
885  /* Add relocation values to the header */
886  if (numValid) {
887  const char ** actualRelocations;
888  int numActual;
889 
890  actualRelocations = xmalloc(numValid * sizeof(*actualRelocations));
891  numActual = 0;
892  for (i = 0; i < numValid; i++) {
893  for (j = 0; j < numRelocations; j++) {
894  if (relocations[j].oldPath == NULL || /* XXX can't happen */
895  strcmp(validRelocations[i], relocations[j].oldPath))
896  /*@innercontinue@*/ continue;
897  /* On install, a relocate to NULL means skip the path. */
898  if (relocations[j].newPath) {
899  actualRelocations[numActual] = relocations[j].newPath;
900  numActual++;
901  }
902  /*@innerbreak@*/ break;
903  }
904  if (j == numRelocations) {
905  actualRelocations[numActual] = validRelocations[i];
906  numActual++;
907  }
908  }
909 
910  if (numActual)
912  (void **) actualRelocations, numActual);
913 
914  actualRelocations = _free(actualRelocations);
915  validRelocations = hfd(validRelocations, validType);
916  }
917 
918  xx = hge(h, RPMTAG_BASENAMES, NULL, &baseNames, &fileCount);
919  xx = hge(h, RPMTAG_DIRINDEXES, NULL, &dirIndexes, NULL);
920  xx = hge(h, RPMTAG_DIRNAMES, NULL, &dirNames, &dirCount);
921  xx = hge(h, RPMTAG_FILEFLAGS, NULL, &fFlags, NULL);
922  xx = hge(h, RPMTAG_FILECOLORS, NULL, &fColors, NULL);
923  xx = hge(h, RPMTAG_FILEMODES, NULL, &fModes, NULL);
924 
925  dColors = alloca(dirCount * sizeof(*dColors));
926  memset(dColors, 0, dirCount * sizeof(*dColors));
927 
928  newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount);
929  memcpy(newDirIndexes, dirIndexes, sizeof(*newDirIndexes) * fileCount);
930  dirIndexes = newDirIndexes;
931 
932  /*
933  * For all relocations, we go through sorted file/relocation lists
934  * backwards so that /usr/local relocations take precedence over /usr
935  * ones.
936  */
937 
938  /* Relocate individual paths. */
939 
940  for (i = fileCount - 1; i >= 0; i--) {
941  fileTypes ft;
942  int fnlen;
943 
944  len = reldel +
945  strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
946  /*@-branchstate@*/
947  if (len >= fileAlloced) {
948  fileAlloced = len * 2;
949  fn = xrealloc(fn, fileAlloced);
950  }
951  /*@=branchstate@*/
952 
953 assert(fn != NULL); /* XXX can't happen */
954  *fn = '\0';
955  fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn;
956 
957 if (fColors != NULL) {
958 /* XXX pkgs may not have unique dirNames, so color all dirNames that match. */
959 for (j = 0; j < dirCount; j++) {
960 if (strcmp(dirNames[dirIndexes[i]], dirNames[j])) /*@innercontinue@*/ continue;
961 dColors[j] |= fColors[i];
962 }
963 }
964 
965  /*
966  * See if this file path needs relocating.
967  */
968  /*
969  * XXX FIXME: Would a bsearch of the (already sorted)
970  * relocation list be a good idea?
971  */
972  for (j = numRelocations - 1; j >= 0; j--) {
973  if (relocations[j].oldPath == NULL) /* XXX can't happen */
974  /*@innercontinue@*/ continue;
975  len = strcmp(relocations[j].oldPath, "/")
976  ? strlen(relocations[j].oldPath)
977  : 0;
978 
979  if (fnlen < len)
980  /*@innercontinue@*/ continue;
981  /*
982  * Only subdirectories or complete file paths may be relocated. We
983  * don't check for '\0' as our directory names all end in '/'.
984  */
985  if (!(fn[len] == '/' || fnlen == len))
986  /*@innercontinue@*/ continue;
987 
988  if (strncmp(relocations[j].oldPath, fn, len))
989  /*@innercontinue@*/ continue;
990  /*@innerbreak@*/ break;
991  }
992  if (j < 0) continue;
993 
994 /*@-nullderef@*/ /* FIX: fModes may be NULL */
995  ft = whatis(fModes[i]);
996 /*@=nullderef@*/
997 
998  /* On install, a relocate to NULL means skip the path. */
999  if (relocations[j].newPath == NULL) {
1000  if (ft == XDIR) {
1001  /* Start with the parent, looking for directory to exclude. */
1002  for (j = dirIndexes[i]; j < dirCount; j++) {
1003  len = strlen(dirNames[j]) - 1;
1004  while (len > 0 && dirNames[j][len-1] == '/') len--;
1005  if (fnlen != len)
1006  /*@innercontinue@*/ continue;
1007  if (strncmp(fn, dirNames[j], fnlen))
1008  /*@innercontinue@*/ continue;
1009  /*@innerbreak@*/ break;
1010  }
1011  }
1012  if (actions) {
1013  actions[i] = FA_SKIPNSTATE;
1014  rpmMessage(RPMMESS_DEBUG, D_("excluding %s %s\n"),
1015  ftstring(ft), fn);
1016  }
1017  continue;
1018  }
1019 
1020  /* Relocation on full paths only, please. */
1021  if (fnlen != len) continue;
1022 
1023  if (actions)
1024  rpmMessage(RPMMESS_DEBUG, D_("relocating %s to %s\n"),
1025  fn, relocations[j].newPath);
1026  nrelocated++;
1027 
1028  strcpy(fn, relocations[j].newPath);
1029  { char * te = strrchr(fn, '/');
1030  if (te) {
1031  if (te > fn) te++; /* root is special */
1032  fnlen = te - fn;
1033  } else
1034  te = fn + strlen(fn);
1035  /*@-nullpass -nullderef@*/ /* LCL: te != NULL here. */
1036  if (strcmp(baseNames[i], te)) /* basename changed too? */
1037  baseNames[i] = alloca_strdup(te);
1038  *te = '\0'; /* terminate new directory name */
1039  /*@=nullpass =nullderef@*/
1040  }
1041 
1042  /* Does this directory already exist in the directory list? */
1043  for (j = 0; j < dirCount; j++) {
1044  if (fnlen != strlen(dirNames[j]))
1045  /*@innercontinue@*/ continue;
1046  if (strncmp(fn, dirNames[j], fnlen))
1047  /*@innercontinue@*/ continue;
1048  /*@innerbreak@*/ break;
1049  }
1050 
1051  if (j < dirCount) {
1052  dirIndexes[i] = j;
1053  continue;
1054  }
1055 
1056  /* Creating new paths is a pita */
1057  if (!haveRelocatedFile) {
1058  const char ** newDirList;
1059 
1060  haveRelocatedFile = 1;
1061  newDirList = xmalloc((dirCount + 1) * sizeof(*newDirList));
1062  for (j = 0; j < dirCount; j++)
1063  newDirList[j] = alloca_strdup(dirNames[j]);
1064  dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE);
1065  dirNames = newDirList;
1066  } else {
1067  dirNames = xrealloc(dirNames,
1068  sizeof(*dirNames) * (dirCount + 1));
1069  }
1070 
1071  dirNames[dirCount] = alloca_strdup(fn);
1072  dirIndexes[i] = dirCount;
1073  dirCount++;
1074  }
1075 
1076  /* Finish off by relocating directories. */
1077  for (i = dirCount - 1; i >= 0; i--) {
1078  for (j = numRelocations - 1; j >= 0; j--) {
1079 
1080  /* XXX Don't autorelocate uncolored directories. */
1081  if (j == p->autorelocatex
1082  && (dColors[i] == 0 || !(dColors[i] & mydColor)))
1083  /*@innercontinue@*/ continue;
1084 
1085  if (relocations[j].oldPath == NULL) /* XXX can't happen */
1086  /*@innercontinue@*/ continue;
1087  len = strcmp(relocations[j].oldPath, "/")
1088  ? strlen(relocations[j].oldPath)
1089  : 0;
1090 
1091  if (len && strncmp(relocations[j].oldPath, dirNames[i], len))
1092  /*@innercontinue@*/ continue;
1093 
1094  /*
1095  * Only subdirectories or complete file paths may be relocated. We
1096  * don't check for '\0' as our directory names all end in '/'.
1097  */
1098  if (dirNames[i][len] != '/')
1099  /*@innercontinue@*/ continue;
1100 
1101  if (relocations[j].newPath) { /* Relocate the path */
1102  const char * s = relocations[j].newPath;
1103  char * t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1);
1104  size_t slen;
1105 
1106  (void) stpcpy( stpcpy(t, s) , dirNames[i] + len);
1107 
1108  /* Unfortunatly rpmCleanPath strips the trailing slash.. */
1109  (void) rpmCleanPath(t);
1110  slen = strlen(t);
1111  t[slen] = '/';
1112  t[slen+1] = '\0';
1113 
1114  if (actions)
1116  D_("relocating directory %s to %s\n"), dirNames[i], t);
1117  dirNames[i] = t;
1118  nrelocated++;
1119  }
1120  }
1121  }
1122 
1123  /* Save original filenames in header and replace (relocated) filenames. */
1124  if (nrelocated) {
1125  int c;
1126  void * d;
1127  rpmTagType t;
1128 
1129  d = NULL;
1130  xx = hge(h, RPMTAG_BASENAMES, &t, &d, &c);
1131  xx = hae(h, RPMTAG_ORIGBASENAMES, t, d, c);
1132  d = hfd(d, t);
1133 
1134  d = NULL;
1135  xx = hge(h, RPMTAG_DIRNAMES, &t, &d, &c);
1136  xx = hae(h, RPMTAG_ORIGDIRNAMES, t, d, c);
1137  d = hfd(d, t);
1138 
1139  d = NULL;
1140  xx = hge(h, RPMTAG_DIRINDEXES, &t, &d, &c);
1141  xx = hae(h, RPMTAG_ORIGDIRINDEXES, t, d, c);
1142  d = hfd(d, t);
1143 
1145  baseNames, fileCount);
1146  fi->bnl = hfd(fi->bnl, RPM_STRING_ARRAY_TYPE);
1147  xx = hge(h, RPMTAG_BASENAMES, NULL, &fi->bnl, &fi->fc);
1148 
1150  dirNames, dirCount);
1151  fi->dnl = hfd(fi->dnl, RPM_STRING_ARRAY_TYPE);
1152  xx = hge(h, RPMTAG_DIRNAMES, NULL, &fi->dnl, &fi->dc);
1153 
1154  xx = hme(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE,
1155  dirIndexes, fileCount);
1156  xx = hge(h, RPMTAG_DIRINDEXES, NULL, &fi->dil, NULL);
1157  }
1158 
1159  baseNames = hfd(baseNames, RPM_STRING_ARRAY_TYPE);
1160  dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE);
1161 /*@-dependenttrans@*/
1162  fn = _free(fn);
1163 /*@=dependenttrans@*/
1164 
1165  return h;
1166 }
1167 /*@=bounds@*/
1168 
1170 {
1171  HFD_t hfd = headerFreeData;
1172 
1173  if (fi == NULL) return NULL;
1174 
1175  if (fi->nrefs > 1)
1176  return rpmfiUnlink(fi, fi->Type);
1177 
1178 /*@-modfilesys@*/
1179 if (_rpmfi_debug < 0)
1180 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, fi->Type, fi->fc);
1181 /*@=modfilesys@*/
1182 
1183  /* Free pre- and post-transaction script and interpreter strings. */
1184  fi->pretrans = _free(fi->pretrans);
1185  fi->pretransprog = _free(fi->pretransprog);
1186  fi->posttrans = _free(fi->posttrans);
1187  fi->posttransprog = _free(fi->posttransprog);
1188 
1189  /*@-branchstate@*/
1190  if (fi->fc > 0) {
1191  fi->bnl = hfd(fi->bnl, -1);
1192  fi->dnl = hfd(fi->dnl, -1);
1193 
1194  fi->flinks = hfd(fi->flinks, -1);
1195  fi->flangs = hfd(fi->flangs, -1);
1196  fi->fdigests = hfd(fi->fdigests, -1);
1197  fi->digests = _free(fi->digests);
1198 
1199  fi->cdict = hfd(fi->cdict, -1);
1200 
1201  fi->fuser = hfd(fi->fuser, -1);
1202  fi->fgroup = hfd(fi->fgroup, -1);
1203 
1204  fi->fstates = _free(fi->fstates);
1205 
1206  /*@-evalorder@*/
1207  if (!fi->keep_header && fi->h == NULL) {
1208  fi->fmtimes = _free(fi->fmtimes);
1209  fi->fmodes = _free(fi->fmodes);
1210  fi->fflags = _free(fi->fflags);
1211  fi->vflags = _free(fi->vflags);
1212  fi->fsizes = _free(fi->fsizes);
1213  fi->frdevs = _free(fi->frdevs);
1214  fi->finodes = _free(fi->finodes);
1215  fi->dil = _free(fi->dil);
1216 
1217  fi->fcolors = _free(fi->fcolors);
1218  fi->fcdictx = _free(fi->fcdictx);
1219  fi->ddict = _free(fi->ddict);
1220  fi->fddictx = _free(fi->fddictx);
1221  fi->fddictn = _free(fi->fddictn);
1222 
1223  }
1224  /*@=evalorder@*/
1225  }
1226  /*@=branchstate@*/
1227 
1228  fi->fsm = freeFSM(fi->fsm);
1229 
1230  fi->fn = _free(fi->fn);
1231  fi->apath = _free(fi->apath);
1232  fi->fmapflags = _free(fi->fmapflags);
1233 
1234  fi->obnl = hfd(fi->obnl, -1);
1235  fi->odnl = hfd(fi->odnl, -1);
1236 
1237  fi->fcontexts = hfd(fi->fcontexts, -1);
1238 
1239  fi->actions = _free(fi->actions);
1240  fi->replacedSizes = _free(fi->replacedSizes);
1241  fi->replaced = _free(fi->replaced);
1242 
1243  fi->h = headerFree(fi->h);
1244 
1245  /*@-nullstate -refcounttrans -usereleased@*/
1246  (void) rpmfiUnlink(fi, fi->Type);
1247  memset(fi, 0, sizeof(*fi)); /* XXX trash and burn */
1248  fi = _free(fi);
1249  /*@=nullstate =refcounttrans =usereleased@*/
1250 
1251  return NULL;
1252 }
1253 
1259 static inline unsigned char nibble(char c)
1260  /*@*/
1261 {
1262  if (c >= '0' && c <= '9')
1263  return (c - '0');
1264  if (c >= 'A' && c <= 'F')
1265  return (c - 'A') + 10;
1266  if (c >= 'a' && c <= 'f')
1267  return (c - 'a') + 10;
1268  return 0;
1269 }
1270 
1271 #define _fdupe(_fi, _data) \
1272  if ((_fi)->_data != NULL) \
1273  (_fi)->_data = memcpy(xmalloc((_fi)->fc * sizeof(*(_fi)->_data)), \
1274  (_fi)->_data, (_fi)->fc * sizeof(*(_fi)->_data))
1275 
1276 /* XXX Ick, not SEF. */
1277 #define _fdupestring(_h, _tag, _data) \
1278  if (hge((_h), (_tag), NULL, &(_data), NULL)) \
1279  _data = xstrdup(_data)
1280 
1281 rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, int flags)
1282 {
1283  HFD_t hfd = headerFreeData;
1284  int scareMem = (flags & 0x1);
1285  HGE_t hge =
1287  rpmte p;
1288  rpmfi fi = NULL;
1289  const char * Type;
1290  uint_32 * uip;
1291  int dnlmax, bnlmax;
1292  unsigned char * t;
1293  int len;
1294  int xx;
1295  int i;
1296 
1297 #ifdef NOTYET /* XXX transaction.c still needs scareMem 1 */
1298 assert(scareMem == 0); /* XXX always allocate memory */
1299 #endif
1300  if (tagN == RPMTAG_BASENAMES) {
1301  Type = "Files";
1302  } else {
1303  Type = "?Type?";
1304  goto exit;
1305  }
1306 
1307  fi = xcalloc(1, sizeof(*fi));
1308  if (fi == NULL) /* XXX can't happen */
1309  goto exit;
1310 
1311  fi->magic = RPMFIMAGIC;
1312  fi->Type = Type;
1313  fi->i = -1;
1314  fi->tagN = tagN;
1315 
1316  fi->hge = hge;
1317  fi->hae = (HAE_t) headerAddEntry;
1318  fi->hme = (HME_t) headerModifyEntry;
1319  fi->hre = (HRE_t) headerRemoveEntry;
1320  fi->hfd = headerFreeData;
1321 
1322  fi->h = (h != NULL && scareMem ? headerLink(h) : NULL);
1323 
1324  if (fi->fsm == NULL)
1325  fi->fsm = newFSM();
1326 
1327  fi->fsm->repackaged = (headerIsEntry(h, RPMTAG_REMOVETID) ? 1 : 0);
1328 
1329  /* 0 means unknown */
1330  xx = hge(h, RPMTAG_ARCHIVESIZE, NULL, &uip, NULL);
1331  fi->archivePos = 0;
1332  fi->archiveSize = (xx ? *uip : 0);
1333 
1334  /* Extract pre- and post-transaction script and interpreter strings. */
1335  _fdupestring(h, RPMTAG_PRETRANS, fi->pretrans);
1336  _fdupestring(h, RPMTAG_PRETRANSPROG, fi->pretransprog);
1337  _fdupestring(h, RPMTAG_POSTTRANS, fi->posttrans);
1338  _fdupestring(h, RPMTAG_POSTTRANSPROG, fi->posttransprog);
1339 
1340  if (!hge(h, RPMTAG_BASENAMES, NULL, &fi->bnl, &fi->fc)) {
1341  fi->fc = 0;
1342  fi->dc = 0;
1343  goto exit;
1344  }
1345  xx = hge(h, RPMTAG_DIRNAMES, NULL, &fi->dnl, &fi->dc);
1346  xx = hge(h, RPMTAG_DIRINDEXES, NULL, &fi->dil, NULL);
1347  xx = hge(h, RPMTAG_FILEMODES, NULL, &fi->fmodes, NULL);
1348  xx = hge(h, RPMTAG_FILEFLAGS, NULL, &fi->fflags, NULL);
1349  xx = hge(h, RPMTAG_FILEVERIFYFLAGS, NULL, &fi->vflags, NULL);
1350  xx = hge(h, RPMTAG_FILESIZES, NULL, &fi->fsizes, NULL);
1351 
1352  xx = hge(h, RPMTAG_FILECOLORS, NULL, &fi->fcolors, NULL);
1353  fi->color = 0;
1354  if (fi->fcolors != NULL)
1355  for (i = 0; i < fi->fc; i++)
1356  fi->color |= fi->fcolors[i];
1357  xx = hge(h, RPMTAG_CLASSDICT, NULL, &fi->cdict, &fi->ncdict);
1358  xx = hge(h, RPMTAG_FILECLASS, NULL, &fi->fcdictx, NULL);
1359 
1360  xx = hge(h, RPMTAG_DEPENDSDICT, NULL, &fi->ddict, &fi->nddict);
1361  xx = hge(h, RPMTAG_FILEDEPENDSX, NULL, &fi->fddictx, NULL);
1362  xx = hge(h, RPMTAG_FILEDEPENDSN, NULL, &fi->fddictn, NULL);
1363 
1364  xx = hge(h, RPMTAG_FILESTATES, NULL, &fi->fstates, NULL);
1365  if (xx == 0 || fi->fstates == NULL)
1366  fi->fstates = xcalloc(fi->fc, sizeof(*fi->fstates));
1367  else
1368  _fdupe(fi, fstates);
1369 
1370  fi->action = FA_UNKNOWN;
1371  fi->flags = 0;
1372 
1373 if (fi->actions == NULL)
1374  fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
1375 
1376  fi->keep_header = (scareMem ? 1 : 0);
1377 
1378  /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
1379  fi->mapflags =
1381 
1382  xx = hge(h, RPMTAG_FILELINKTOS, NULL, &fi->flinks, NULL);
1383  xx = hge(h, RPMTAG_FILELANGS, NULL, &fi->flangs, NULL);
1384 
1385  fi->digestalgo = PGPHASHALGO_MD5;
1386  fi->digestlen = 16;
1387  fi->fdigestalgos = NULL;
1388  xx = hge(h, RPMTAG_FILEDIGESTALGOS, NULL, &fi->fdigestalgos, NULL);
1389  if (fi->fdigestalgos) {
1390  int dalgo = 0;
1391  /* XXX Insure that all algorithms are either 0 or constant. */
1392  for (i = 0; i < fi->fc; i++) {
1393  if (fi->fdigestalgos[i] == 0)
1394  continue;
1395  if (dalgo == 0)
1396  dalgo = fi->fdigestalgos[i];
1397  else
1398 assert(dalgo == fi->fdigestalgos[i]);
1399  }
1400  fi->digestalgo = dalgo;
1401  switch (dalgo) {
1402  case PGPHASHALGO_MD5: fi->digestlen = 128/8; break;
1403  case PGPHASHALGO_SHA1: fi->digestlen = 160/8; break;
1404  case PGPHASHALGO_RIPEMD128: fi->digestlen = 128/8; break;
1405  case PGPHASHALGO_RIPEMD160: fi->digestlen = 160/8; break;
1406  case PGPHASHALGO_SHA256: fi->digestlen = 256/8; break;
1407  case PGPHASHALGO_SHA384: fi->digestlen = 384/8; break;
1408  case PGPHASHALGO_SHA512: fi->digestlen = 512/8; break;
1409  case PGPHASHALGO_CRC32: fi->digestlen = 32/8; break;
1410  }
1411  fi->fdigestalgos = NULL;
1412  }
1413 
1414  fi->fdigests = NULL;
1415  xx = hge(h, RPMTAG_FILEDIGESTS, NULL, &fi->fdigests, NULL);
1416 
1417  fi->digests = NULL;
1418  if (fi->fdigests) {
1419  t = xmalloc(fi->fc * fi->digestlen);
1420  fi->digests = t;
1421  for (i = 0; i < fi->fc; i++) {
1422  const char * fdigests;
1423  int j;
1424 
1425  fdigests = fi->fdigests[i];
1426  if (!(fdigests && *fdigests != '\0')) {
1427  memset(t, 0, fi->digestlen);
1428  t += fi->digestlen;
1429  continue;
1430  }
1431  for (j = 0; j < fi->digestlen; j++, t++, fdigests += 2)
1432  *t = (nibble(fdigests[0]) << 4) | nibble(fdigests[1]);
1433  }
1434  fi->fdigests = hfd(fi->fdigests, -1);
1435  }
1436 
1437  /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes, or fcontexts */
1438  xx = hge(h, RPMTAG_FILEMTIMES, NULL, &fi->fmtimes, NULL);
1439  xx = hge(h, RPMTAG_FILERDEVS, NULL, &fi->frdevs, NULL);
1440  xx = hge(h, RPMTAG_FILEINODES, NULL, &fi->finodes, NULL);
1441  xx = hge(h, RPMTAG_FILECONTEXTS, NULL, &fi->fcontexts, NULL);
1442 
1443  fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
1444 
1445  xx = hge(h, RPMTAG_FILEUSERNAME, NULL, &fi->fuser, NULL);
1446  xx = hge(h, RPMTAG_FILEGROUPNAME, NULL, &fi->fgroup, NULL);
1447 
1448  if (ts != NULL)
1449  if (fi != NULL)
1450  if ((p = rpmtsRelocateElement(ts)) != NULL && rpmteType(p) == TR_ADDED
1453  {
1454  const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL);
1455  const char * errstr;
1456  char * newPath;
1457  Header foo;
1458 
1459  /* XXX error handling. */
1460  newPath = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
1461  fmt = _free(fmt);
1462 
1463 #if __ia64__
1464  /* XXX On ia64, change leading /emul/ix86 -> /emul/ia32, ick. */
1465  if (newPath != NULL && *newPath != '\0'
1466  && strlen(newPath) >= (sizeof("/emul/i386")-1)
1467  && newPath[0] == '/' && newPath[1] == 'e' && newPath[2] == 'm'
1468  && newPath[3] == 'u' && newPath[4] == 'l' && newPath[5] == '/'
1469  && newPath[6] == 'i' && newPath[8] == '8' && newPath[9] == '6')
1470  {
1471  newPath[7] = 'a';
1472  newPath[8] = '3';
1473  newPath[9] = '2';
1474  }
1475 #endif
1476 
1477  /* XXX Make sure autoreloc is not already specified. */
1478  i = p->nrelocs;
1479  if (newPath != NULL && *newPath != '\0' && p->relocs != NULL)
1480  for (i = 0; i < p->nrelocs; i++) {
1481 /*@-nullpass@*/ /* XXX {old,new}Path might be NULL */
1482  if (strcmp(p->relocs[i].oldPath, "/"))
1483  continue;
1484  if (strcmp(p->relocs[i].newPath, newPath))
1485  continue;
1486 /*@=nullpass@*/
1487  break;
1488  }
1489 
1490  /* XXX test for incompatible arch triggering autorelocation is dumb. */
1491  /* XXX DIEDIEDIE: used to test '... && p->archScore == 0' */
1492  if (newPath != NULL && *newPath != '\0' && i == p->nrelocs) {
1493 
1494  p->relocs =
1495  xrealloc(p->relocs, (p->nrelocs + 2) * sizeof(*p->relocs));
1496  p->relocs[p->nrelocs].oldPath = xstrdup("/");
1497  p->relocs[p->nrelocs].newPath = xstrdup(newPath);
1498  p->autorelocatex = p->nrelocs;
1499  p->nrelocs++;
1500  p->relocs[p->nrelocs].oldPath = NULL;
1501  p->relocs[p->nrelocs].newPath = NULL;
1502  }
1503  newPath = _free(newPath);
1504 
1505 /* XXX DYING */
1506 if (fi->actions == NULL)
1507  fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
1508  /*@-compdef@*/ /* FIX: fi->digests undefined */
1509  foo = relocateFileList(ts, fi, h, fi->actions);
1510  /*@=compdef@*/
1511  fi->h = headerFree(fi->h);
1512  fi->h = headerLink(foo);
1513  foo = headerFree(foo);
1514  }
1515 
1516  if (!scareMem) {
1517  _fdupe(fi, fmtimes);
1518  _fdupe(fi, frdevs);
1519  _fdupe(fi, finodes);
1520  _fdupe(fi, fsizes);
1521  _fdupe(fi, fflags);
1522  _fdupe(fi, vflags);
1523  _fdupe(fi, fmodes);
1524  _fdupe(fi, dil);
1525 
1526  _fdupe(fi, fcolors);
1527  _fdupe(fi, fcdictx);
1528 
1529  if (fi->ddict != NULL)
1530  fi->ddict = memcpy(xmalloc(fi->nddict * sizeof(*fi->ddict)),
1531  fi->ddict, fi->nddict * sizeof(*fi->ddict));
1532 
1533  _fdupe(fi, fddictx);
1534  _fdupe(fi, fddictn);
1535 
1536  fi->h = headerFree(fi->h);
1537  }
1538 
1539  dnlmax = -1;
1540  for (i = 0; i < fi->dc; i++) {
1541  if ((len = strlen(fi->dnl[i])) > dnlmax)
1542  dnlmax = len;
1543  }
1544  bnlmax = -1;
1545  for (i = 0; i < fi->fc; i++) {
1546  if ((len = strlen(fi->bnl[i])) > bnlmax)
1547  bnlmax = len;
1548  }
1549  fi->fnlen = dnlmax + bnlmax + 1;
1550  fi->fn = NULL;
1551 
1552  fi->dperms = 0755;
1553  fi->fperms = 0644;
1554 
1555 exit:
1556 /*@-modfilesys@*/
1557 if (_rpmfi_debug < 0)
1558 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, Type, (fi ? fi->fc : 0));
1559 /*@=modfilesys@*/
1560 
1561  /*@-compdef -nullstate@*/ /* FIX: rpmfi null annotations */
1562  return rpmfiLink(fi, (fi ? fi->Type : NULL));
1563  /*@=compdef =nullstate@*/
1564 }
1565 
1567  /*@out@*/ const char *** fclassp, /*@out@*/ int * fcp)
1568 {
1569  int scareMem = 0;
1570  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1571  const char * FClass;
1572  const char ** av;
1573  int ac;
1574  size_t nb;
1575  char * t;
1576 
1577  if ((ac = rpmfiFC(fi)) <= 0) {
1578  av = NULL;
1579  ac = 0;
1580  goto exit;
1581  }
1582 
1583  /* Compute size of file class argv array blob. */
1584  nb = (ac + 1) * sizeof(*av);
1585  fi = rpmfiInit(fi, 0);
1586  if (fi != NULL)
1587  while (rpmfiNext(fi) >= 0) {
1588  FClass = rpmfiFClass(fi);
1589  if (FClass && *FClass != '\0')
1590  nb += strlen(FClass);
1591  nb += 1;
1592  }
1593 
1594  /* Create and load file class argv array. */
1595  av = xmalloc(nb);
1596  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1597  ac = 0;
1598  fi = rpmfiInit(fi, 0);
1599  if (fi != NULL)
1600  while (rpmfiNext(fi) >= 0) {
1601  FClass = rpmfiFClass(fi);
1602  av[ac++] = t;
1603  if (FClass && *FClass != '\0')
1604  t = stpcpy(t, FClass);
1605  *t++ = '\0';
1606  }
1607  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1608  /*@=branchstate@*/
1609 
1610 exit:
1611  fi = rpmfiFree(fi);
1612  /*@-branchstate@*/
1613  if (fclassp)
1614  *fclassp = av;
1615  else
1616  av = _free(av);
1617  /*@=branchstate@*/
1618  if (fcp) *fcp = ac;
1619 }
1620 
1622  /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
1623 {
1624  int scareMem = 0;
1625  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1626  const char * fcontext;
1627  const char ** av;
1628  int ac;
1629  size_t nb;
1630  char * t;
1631 
1632  if ((ac = rpmfiFC(fi)) <= 0) {
1633  av = NULL;
1634  ac = 0;
1635  goto exit;
1636  }
1637 
1638  /* Compute size of argv array blob. */
1639  nb = (ac + 1) * sizeof(*av);
1640  fi = rpmfiInit(fi, 0);
1641  if (fi != NULL)
1642  while (rpmfiNext(fi) >= 0) {
1643  fcontext = rpmfiFContext(fi);
1644  if (fcontext && *fcontext != '\0')
1645  nb += strlen(fcontext);
1646  nb += 1;
1647  }
1648 
1649  /* Create and load argv array. */
1650  av = xmalloc(nb);
1651  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1652  ac = 0;
1653  fi = rpmfiInit(fi, 0);
1654  if (fi != NULL)
1655  while (rpmfiNext(fi) >= 0) {
1656  fcontext = rpmfiFContext(fi);
1657  av[ac++] = t;
1658  if (fcontext && *fcontext != '\0')
1659  t = stpcpy(t, fcontext);
1660  *t++ = '\0';
1661  }
1662  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1663  /*@=branchstate@*/
1664 
1665 exit:
1666  fi = rpmfiFree(fi);
1667  /*@-branchstate@*/
1668  if (fcontextp)
1669  *fcontextp = av;
1670  else
1671  av = _free(av);
1672  /*@=branchstate@*/
1673  if (fcp) *fcp = ac;
1674 }
1675 
1677  /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
1678 {
1679  int scareMem = 0;
1680  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1681  const char ** av;
1682  int ac;
1683  size_t nb;
1684  char * t;
1685  char * fctxt = NULL;
1686  size_t fctxtlen = 0;
1687  int * fcnb;
1688 
1689  if ((ac = rpmfiFC(fi)) <= 0) {
1690  av = NULL;
1691  ac = 0;
1692  goto exit;
1693  }
1694 
1695  /* Compute size of argv array blob, concatenating file contexts. */
1696  nb = ac * sizeof(*fcnb);
1697  fcnb = memset(alloca(nb), 0, nb);
1698  ac = 0;
1699  fi = rpmfiInit(fi, 0);
1700  if (fi != NULL)
1701  while (rpmfiNext(fi) >= 0) {
1702  const char * fn = rpmfiFN(fi);
1703  security_context_t scon;
1704 
1705  fcnb[ac] = lgetfilecon(fn, &scon);
1706 /*@-branchstate@*/
1707  if (fcnb[ac] > 0) {
1708  fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
1709  memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
1710  fctxtlen += fcnb[ac];
1711  freecon(scon);
1712  }
1713 /*@=branchstate@*/
1714  ac++;
1715  }
1716 
1717  /* Create and load argv array from concatenated file contexts. */
1718  nb = (ac + 1) * sizeof(*av) + fctxtlen;
1719  av = xmalloc(nb);
1720  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1721  if (fctxt != NULL && fctxtlen > 0)
1722  (void) memcpy(t, fctxt, fctxtlen);
1723  ac = 0;
1724  fi = rpmfiInit(fi, 0);
1725  if (fi != NULL)
1726  while (rpmfiNext(fi) >= 0) {
1727  av[ac] = "";
1728  if (fcnb[ac] > 0) {
1729  av[ac] = t;
1730  t += fcnb[ac];
1731  }
1732  ac++;
1733  }
1734  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1735 
1736 exit:
1737  fi = rpmfiFree(fi);
1738  /*@-branchstate@*/
1739  if (fcontextp)
1740  *fcontextp = av;
1741  else
1742  av = _free(av);
1743  /*@=branchstate@*/
1744  if (fcp) *fcp = ac;
1745 }
1746 
1748  /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
1749 {
1750  int scareMem = 0;
1751  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1752  const char ** av = NULL;
1753  int ac;
1754  size_t nb;
1755  char * t;
1756  char * fctxt = NULL;
1757  size_t fctxtlen = 0;
1758  int * fcnb;
1759 
1760  if ((ac = rpmfiFC(fi)) <= 0) {
1761  ac = 0;
1762  goto exit;
1763  }
1764 
1765  /* Read security context patterns. */
1766  { const char *fn = rpmGetPath("%{?__file_context_path}", NULL);
1767  if (fn != NULL && *fn != '\0')
1768  matchpathcon_init(fn);
1769  fn = _free(fn);
1770  }
1771 
1772  /* Compute size of argv array blob, concatenating file contexts. */
1773  nb = ac * sizeof(*fcnb);
1774  fcnb = memset(alloca(nb), 0, nb);
1775  ac = 0;
1776  fi = rpmfiInit(fi, 0);
1777  if (fi != NULL)
1778  while (rpmfiNext(fi) >= 0) {
1779  const char * fn = rpmfiFN(fi);
1780  mode_t fmode = rpmfiFMode(fi);
1781  security_context_t scon;
1782 
1783  scon = NULL;
1784  if (matchpathcon(fn, fmode, &scon) == 0 && scon != NULL) {
1785  fcnb[ac] = strlen(scon) + 1;
1786 /*@-branchstate@*/
1787  if (fcnb[ac] > 0) {
1788  fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
1789  memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
1790  fctxtlen += fcnb[ac];
1791  }
1792 /*@=branchstate@*/
1793  freecon(scon);
1794  }
1795  ac++;
1796  }
1797 
1798  /* Create and load argv array from concatenated file contexts. */
1799  nb = (ac + 1) * sizeof(*av) + fctxtlen;
1800  av = xmalloc(nb);
1801  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1802  (void) memcpy(t, fctxt, fctxtlen);
1803  ac = 0;
1804  fi = rpmfiInit(fi, 0);
1805  if (fi != NULL)
1806  while (rpmfiNext(fi) >= 0) {
1807  av[ac] = "";
1808  if (fcnb[ac] > 0) {
1809  av[ac] = t;
1810  t += fcnb[ac];
1811  }
1812  ac++;
1813  }
1814  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1815 
1816 exit:
1817  fi = rpmfiFree(fi);
1818  /*@-branchstate@*/
1819  if (fcontextp)
1820  *fcontextp = av;
1821  else
1822  av = _free(av);
1823  /*@=branchstate@*/
1824  if (fcp) *fcp = ac;
1825 }
1826 
1828  /*@out@*/ const char *** fdepsp, /*@out@*/ int * fcp)
1829 {
1830  int scareMem = 0;
1831  rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
1832  rpmds ds = NULL;
1833  const char ** av;
1834  int ac;
1835  size_t nb;
1836  char * t;
1837  char deptype = 'R';
1838  char mydt;
1839  const char * DNEVR;
1840  const uint_32 * ddict;
1841  unsigned ix;
1842  int ndx;
1843 
1844  if ((ac = rpmfiFC(fi)) <= 0) {
1845  av = NULL;
1846  ac = 0;
1847  goto exit;
1848  }
1849 
1850  if (tagN == RPMTAG_PROVIDENAME)
1851  deptype = 'P';
1852  else if (tagN == RPMTAG_REQUIRENAME)
1853  deptype = 'R';
1854 
1855  ds = rpmdsNew(h, tagN, scareMem);
1856 
1857  /* Compute size of file depends argv array blob. */
1858  nb = (ac + 1) * sizeof(*av);
1859  fi = rpmfiInit(fi, 0);
1860  if (fi != NULL)
1861  while (rpmfiNext(fi) >= 0) {
1862  ddict = NULL;
1863  ndx = rpmfiFDepends(fi, &ddict);
1864  if (ddict != NULL)
1865  while (ndx-- > 0) {
1866  ix = *ddict++;
1867  mydt = ((ix >> 24) & 0xff);
1868  if (mydt != deptype)
1869  /*@innercontinue@*/ continue;
1870  ix &= 0x00ffffff;
1871  (void) rpmdsSetIx(ds, ix-1);
1872  if (rpmdsNext(ds) < 0)
1873  /*@innercontinue@*/ continue;
1874  DNEVR = rpmdsDNEVR(ds);
1875  if (DNEVR != NULL)
1876  nb += strlen(DNEVR+2) + 1;
1877  }
1878  nb += 1;
1879  }
1880 
1881  /* Create and load file depends argv array. */
1882  av = xmalloc(nb);
1883  t = ((char *) av) + ((ac + 1) * sizeof(*av));
1884  ac = 0;
1885  /*@-branchstate@*/
1886  fi = rpmfiInit(fi, 0);
1887  if (fi != NULL)
1888  while (rpmfiNext(fi) >= 0) {
1889  av[ac++] = t;
1890  ddict = NULL;
1891  ndx = rpmfiFDepends(fi, &ddict);
1892  if (ddict != NULL)
1893  while (ndx-- > 0) {
1894  ix = *ddict++;
1895  mydt = ((ix >> 24) & 0xff);
1896  if (mydt != deptype)
1897  /*@innercontinue@*/ continue;
1898  ix &= 0x00ffffff;
1899  (void) rpmdsSetIx(ds, ix-1);
1900  if (rpmdsNext(ds) < 0)
1901  /*@innercontinue@*/ continue;
1902  DNEVR = rpmdsDNEVR(ds);
1903  if (DNEVR != NULL) {
1904  t = stpcpy(t, DNEVR+2);
1905  *t++ = ' ';
1906  *t = '\0';
1907  }
1908  }
1909  *t++ = '\0';
1910  }
1911  /*@=branchstate@*/
1912  av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */
1913 
1914 exit:
1915  fi = rpmfiFree(fi);
1916  ds = rpmdsFree(ds);
1917  /*@-branchstate@*/
1918  if (fdepsp)
1919  *fdepsp = av;
1920  else
1921  av = _free(av);
1922  /*@=branchstate@*/
1923  if (fcp) *fcp = ac;
1924 }