rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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
46 struct rpmRelocation_s {
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
123 int rpmfiIsSource(rpmfi fi)
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
168 size_t rpmfiFNMaxLen(rpmfi fi)
169 {
170 if (fi != NULL)
171 return fi->fnlen;
172 return 0;
173 }
174
175 rpmuint32_t rpmfiFFlags(rpmfi fi)
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
186 rpmuint32_t rpmfiSetFFlags(rpmfi fi, rpmuint32_t FFlags)
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
199 rpmuint32_t rpmfiVFlags(rpmfi fi)
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
210 rpmuint32_t rpmfiSetVFlags(rpmfi fi, rpmuint32_t VFlags)
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
223 rpmuint16_t rpmfiFMode(rpmfi fi)
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
234 rpmfileState rpmfiFState(rpmfi fi)
235 {
236 rpmfileState fstate = RPMFILE_STATE_MISSING;
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
245 rpmfileState rpmfiSetFState(rpmfi fi, rpmfileState fstate)
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
286 rpmuint32_t rpmfiFSize(rpmfi fi)
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
297 rpmuint16_t rpmfiFRdev(rpmfi fi)
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
308 rpmuint32_t rpmfiFInode(rpmfi fi)
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
319 rpmuint32_t rpmfiColor(rpmfi fi)
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
329 rpmuint32_t rpmfiFColor(rpmfi fi)
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
364 rpmuint32_t rpmfiFDepends(rpmfi fi, const rpmuint32_t ** fddictp)
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
385 rpmuint32_t rpmfiFNlink(rpmfi fi)
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
405 rpmuint32_t rpmfiFMtime(rpmfi fi)
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
460 int rpmfiNext(rpmfi fi)
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
496 int rpmfiNextD(rpmfi fi)
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
557 static rpmFileTypes rpmfiWhatis(rpmuint16_t mode)
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
723 Header relocateFileList(const rpmts ts, rpmfi fi,
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);
839 rpmpsAppend(ps, RPMPROB_BADRELOCATE,
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)
1131 rpmlog(RPMLOG_DEBUG,
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
1209 int rpmfiSetHeader(rpmfi fi, Header h)
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@*/
1290 rpmioPool _rpmfiPool;
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 =
1447 IOSM_MAP_PATH | IOSM_MAP_MODE | IOSM_MAP_UID | IOSM_MAP_GID;
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
1526 && headerIsEntry(h, RPMTAG_SOURCERPM)
1527 && !headerIsEntry(h, RPMTAG_ORIGBASENAMES))
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
1666 rpmRelocation rpmfiFreeRelocations(rpmRelocation relocs)
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
1679 rpmRelocation rpmfiDupeRelocations(rpmRelocation relocs, int * nrelocsp)
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
1806 void rpmfiBuildFClasses(Header h,
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
1858 void rpmfiBuildFContexts(Header h,
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
1910 void rpmfiBuildFSContexts(Header h,
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
1978 void rpmfiBuildREContexts(Header h,
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 @*/
2053 matchpathcon_fini();
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
2063 void rpmfiBuildFDeps(Header h, rpmTag tagN,
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 }