rpm
4.5
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> 00009 #include <rpmlib.h> 00010 00011 #include "cpio.h" /* XXX CPIO_FOO */ 00012 #include "fsm.h" /* XXX newFSM() */ 00013 00014 #include "rpmds.h" 00015 00016 #include "legacy.h" 00017 00018 #define _RPMFI_INTERNAL 00019 #include "rpmfi.h" 00020 00021 #define _RPMTE_INTERNAL /* relocations */ 00022 #include "rpmte.h" 00023 #include "rpmts.h" 00024 00025 #include "misc.h" /* XXX stripTrailingChar */ 00026 #include "rpmmacro.h" /* XXX rpmCleanPath */ 00027 00028 #include "debug.h" 00029 00030 /*@access rpmte @*/ 00031 /*@access FSM_t @*/ /* XXX fsm->repackaged */ 00032 00033 /*@unchecked@*/ 00034 int _rpmfi_debug = 0; 00035 00036 rpmfi XrpmfiUnlink(rpmfi fi, const char * msg, const char * fn, unsigned ln) 00037 { 00038 if (fi == NULL) return NULL; 00039 /*@-modfilesys@*/ 00040 if (_rpmfi_debug && msg != NULL) 00041 fprintf(stderr, "--> fi %p -- %d %s at %s:%u\n", fi, fi->nrefs, msg, fn, ln); 00042 /*@=modfilesys@*/ 00043 fi->nrefs--; 00044 return NULL; 00045 } 00046 00047 rpmfi XrpmfiLink(rpmfi fi, const char * msg, const char * fn, unsigned ln) 00048 { 00049 if (fi == NULL) return NULL; 00050 fi->nrefs++; 00051 /*@-modfilesys@*/ 00052 if (_rpmfi_debug && msg != NULL) 00053 fprintf(stderr, "--> fi %p ++ %d %s at %s:%u\n", fi, fi->nrefs, msg, fn, ln); 00054 /*@=modfilesys@*/ 00055 /*@-refcounttrans@*/ return fi; /*@=refcounttrans@*/ 00056 } 00057 00058 int rpmfiFC(rpmfi fi) 00059 { 00060 return (fi != NULL ? fi->fc : 0); 00061 } 00062 00063 int rpmfiDC(rpmfi fi) 00064 { 00065 return (fi != NULL ? fi->dc : 0); 00066 } 00067 00068 #ifdef NOTYET 00069 int rpmfiDI(rpmfi fi) 00070 { 00071 } 00072 #endif 00073 00074 int rpmfiFX(rpmfi fi) 00075 { 00076 return (fi != NULL ? fi->i : -1); 00077 } 00078 00079 int rpmfiSetFX(rpmfi fi, int fx) 00080 { 00081 int i = -1; 00082 00083 if (fi != NULL && fx >= 0 && fx < fi->fc) { 00084 i = fi->i; 00085 fi->i = fx; 00086 /*@-boundsread@*/ 00087 fi->j = fi->dil[fi->i]; 00088 /*@=boundsread@*/ 00089 } 00090 return i; 00091 } 00092 00093 int rpmfiDX(rpmfi fi) 00094 { 00095 return (fi != NULL ? fi->j : -1); 00096 } 00097 00098 int rpmfiSetDX(rpmfi fi, int dx) 00099 { 00100 int j = -1; 00101 00102 if (fi != NULL && dx >= 0 && dx < fi->dc) { 00103 j = fi->j; 00104 fi->j = dx; 00105 } 00106 return j; 00107 } 00108 00109 const char * rpmfiBN(rpmfi fi) 00110 { 00111 const char * BN = NULL; 00112 00113 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00114 /*@-boundsread@*/ 00115 if (fi->bnl != NULL) 00116 BN = fi->bnl[fi->i]; 00117 /*@=boundsread@*/ 00118 } 00119 return BN; 00120 } 00121 00122 const char * rpmfiDN(rpmfi fi) 00123 { 00124 const char * DN = NULL; 00125 00126 if (fi != NULL && fi->j >= 0 && fi->j < fi->dc) { 00127 /*@-boundsread@*/ 00128 if (fi->dnl != NULL) 00129 DN = fi->dnl[fi->j]; 00130 /*@=boundsread@*/ 00131 } 00132 return DN; 00133 } 00134 00135 const char * rpmfiFN(rpmfi fi) 00136 { 00137 const char * FN = ""; 00138 00139 /*@-branchstate@*/ 00140 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00141 const char *dn; 00142 char * t; 00143 if (fi->fn == NULL) 00144 fi->fn = xmalloc(fi->fnlen); 00145 FN = t = fi->fn; 00146 (void) urlPath(fi->dnl[fi->dil[fi->i]], &dn); 00147 /*@-boundswrite@*/ 00148 *t = '\0'; 00149 t = stpcpy(t, dn); 00150 t = stpcpy(t, fi->bnl[fi->i]); 00151 /*@=boundswrite@*/ 00152 } 00153 /*@=branchstate@*/ 00154 return FN; 00155 } 00156 00157 uint_32 rpmfiFFlags(rpmfi fi) 00158 { 00159 uint_32 FFlags = 0; 00160 00161 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00162 /*@-boundsread@*/ 00163 if (fi->fflags != NULL) 00164 FFlags = fi->fflags[fi->i]; 00165 /*@=boundsread@*/ 00166 } 00167 return FFlags; 00168 } 00169 00170 uint_32 rpmfiSetFFlags(rpmfi fi, uint_32 FFlags) 00171 { 00172 uint_32 oFFlags = 0; 00173 00174 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00175 /*@-boundsread@*/ 00176 if (fi->fflags != NULL && fi->h == NULL) { 00177 oFFlags = fi->fflags[fi->i]; 00178 *((uint_32 *)(fi->fflags + fi->i)) = FFlags; 00179 } 00180 /*@=boundsread@*/ 00181 } 00182 return oFFlags; 00183 } 00184 00185 uint_32 rpmfiVFlags(rpmfi fi) 00186 { 00187 uint_32 VFlags = 0; 00188 00189 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00190 /*@-boundsread@*/ 00191 if (fi->vflags != NULL) 00192 VFlags = fi->vflags[fi->i]; 00193 /*@=boundsread@*/ 00194 } 00195 return VFlags; 00196 } 00197 00198 uint_32 rpmfiSetVFlags(rpmfi fi, uint_32 VFlags) 00199 { 00200 uint_32 oVFlags = 0; 00201 00202 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00203 /*@-boundsread@*/ 00204 if (fi->vflags != NULL && fi->h == NULL) { 00205 oVFlags = fi->vflags[fi->i]; 00206 *((uint_32 *)(fi->vflags + fi->i)) = VFlags; 00207 } 00208 /*@=boundsread@*/ 00209 } 00210 return oVFlags; 00211 } 00212 00213 int_16 rpmfiFMode(rpmfi fi) 00214 { 00215 int_16 fmode = 0; 00216 00217 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00218 /*@-boundsread@*/ 00219 if (fi->fmodes != NULL) 00220 fmode = fi->fmodes[fi->i]; 00221 /*@=boundsread@*/ 00222 } 00223 return fmode; 00224 } 00225 00226 rpmfileState rpmfiFState(rpmfi fi) 00227 { 00228 rpmfileState fstate = RPMFILE_STATE_MISSING; 00229 00230 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00231 /*@-boundsread@*/ 00232 if (fi->fstates != NULL) 00233 fstate = fi->fstates[fi->i]; 00234 /*@=boundsread@*/ 00235 } 00236 return fstate; 00237 } 00238 00239 rpmfileState rpmfiSetFState(rpmfi fi, rpmfileState fstate) 00240 { 00241 int_32 ofstate = 0; 00242 00243 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00244 /*@-boundsread@*/ 00245 if (fi->fstates != NULL) { 00246 ofstate = fi->fstates[fi->i]; 00247 fi->fstates[fi->i] = fstate; 00248 } 00249 /*@=boundsread@*/ 00250 } 00251 return ofstate; 00252 } 00253 00254 const unsigned char * rpmfiDigest(rpmfi fi, int * algop, size_t * lenp) 00255 { 00256 unsigned char * digest = NULL; 00257 00258 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00259 /*@-boundsread@*/ 00260 if (fi->digests != NULL) { 00261 digest = fi->digests + (fi->digestlen * fi->i); 00262 if (algop != NULL) 00263 *algop = (fi->fdigestalgos 00264 ? fi->fdigestalgos[fi->i] : fi->digestalgo); 00265 if (lenp != NULL) 00266 *lenp = fi->digestlen; 00267 } 00268 /*@=boundsread@*/ 00269 } 00270 return digest; 00271 } 00272 00273 const char * rpmfiFLink(rpmfi fi) 00274 { 00275 const char * flink = NULL; 00276 00277 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00278 /*@-boundsread@*/ 00279 if (fi->flinks != NULL) 00280 flink = fi->flinks[fi->i]; 00281 /*@=boundsread@*/ 00282 } 00283 return flink; 00284 } 00285 00286 int_32 rpmfiFSize(rpmfi fi) 00287 { 00288 int_32 fsize = 0; 00289 00290 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00291 /*@-boundsread@*/ 00292 if (fi->fsizes != NULL) 00293 fsize = fi->fsizes[fi->i]; 00294 /*@=boundsread@*/ 00295 } 00296 return fsize; 00297 } 00298 00299 int_16 rpmfiFRdev(rpmfi fi) 00300 { 00301 int_16 frdev = 0; 00302 00303 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00304 /*@-boundsread@*/ 00305 if (fi->frdevs != NULL) 00306 frdev = fi->frdevs[fi->i]; 00307 /*@=boundsread@*/ 00308 } 00309 return frdev; 00310 } 00311 00312 int_32 rpmfiFInode(rpmfi fi) 00313 { 00314 int_32 finode = 0; 00315 00316 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00317 /*@-boundsread@*/ 00318 if (fi->finodes != NULL) 00319 finode = fi->finodes[fi->i]; 00320 /*@=boundsread@*/ 00321 } 00322 return finode; 00323 } 00324 00325 uint_32 rpmfiColor(rpmfi fi) 00326 { 00327 uint_32 color = 0; 00328 00329 if (fi != NULL) 00330 /* XXX ignore all but lsnibble for now. */ 00331 color = fi->color & 0xf; 00332 return color; 00333 } 00334 00335 uint_32 rpmfiFColor(rpmfi fi) 00336 { 00337 uint_32 fcolor = 0; 00338 00339 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00340 /*@-boundsread@*/ 00341 if (fi->fcolors != NULL) 00342 /* XXX ignore all but lsnibble for now. */ 00343 fcolor = (fi->fcolors[fi->i] & 0x0f); 00344 /*@=boundsread@*/ 00345 } 00346 return fcolor; 00347 } 00348 00349 const char * rpmfiFClass(rpmfi fi) 00350 { 00351 const char * fclass = NULL; 00352 int cdictx; 00353 00354 if (fi != NULL && fi->fcdictx != NULL && fi->i >= 0 && fi->i < fi->fc) { 00355 /*@-boundsread@*/ 00356 cdictx = fi->fcdictx[fi->i]; 00357 if (fi->cdict != NULL && cdictx >= 0 && cdictx < fi->ncdict) 00358 fclass = fi->cdict[cdictx]; 00359 /*@=boundsread@*/ 00360 } 00361 return fclass; 00362 } 00363 00364 const char * rpmfiFContext(rpmfi fi) 00365 { 00366 const char * fcontext = NULL; 00367 00368 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00369 /*@-boundsread@*/ 00370 if (fi->fcontexts != NULL) 00371 fcontext = fi->fcontexts[fi->i]; 00372 /*@=boundsread@*/ 00373 } 00374 return fcontext; 00375 } 00376 00377 int_32 rpmfiFDepends(rpmfi fi, const uint_32 ** fddictp) 00378 { 00379 int fddictx = -1; 00380 int fddictn = 0; 00381 const uint_32 * fddict = NULL; 00382 00383 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00384 /*@-boundsread@*/ 00385 if (fi->fddictn != NULL) 00386 fddictn = fi->fddictn[fi->i]; 00387 if (fddictn > 0 && fi->fddictx != NULL) 00388 fddictx = fi->fddictx[fi->i]; 00389 if (fi->ddict != NULL && fddictx >= 0 && (fddictx+fddictn) <= fi->nddict) 00390 fddict = fi->ddict + fddictx; 00391 /*@=boundsread@*/ 00392 } 00393 /*@-boundswrite -dependenttrans -onlytrans @*/ 00394 if (fddictp) 00395 *fddictp = fddict; 00396 /*@=boundswrite =dependenttrans =onlytrans @*/ 00397 return fddictn; 00398 } 00399 00400 int_32 rpmfiFNlink(rpmfi fi) 00401 { 00402 int_32 nlink = 0; 00403 00404 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00405 /* XXX rpm-2.3.12 has not RPMTAG_FILEINODES */ 00406 /*@-boundsread@*/ 00407 if (fi->finodes && fi->frdevs) { 00408 int_32 finode = fi->finodes[fi->i]; 00409 int_16 frdev = fi->frdevs[fi->i]; 00410 int j; 00411 00412 for (j = 0; j < fi->fc; j++) { 00413 if (fi->frdevs[j] == frdev && fi->finodes[j] == finode) 00414 nlink++; 00415 } 00416 } 00417 /*@=boundsread@*/ 00418 } 00419 return nlink; 00420 } 00421 00422 int_32 rpmfiFMtime(rpmfi fi) 00423 { 00424 int_32 fmtime = 0; 00425 00426 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00427 /*@-boundsread@*/ 00428 if (fi->fmtimes != NULL) 00429 fmtime = fi->fmtimes[fi->i]; 00430 /*@=boundsread@*/ 00431 } 00432 return fmtime; 00433 } 00434 00435 const char * rpmfiFUser(rpmfi fi) 00436 { 00437 const char * fuser = NULL; 00438 00439 /* XXX add support for ancient RPMTAG_FILEUIDS? */ 00440 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00441 /*@-boundsread@*/ 00442 if (fi->fuser != NULL) 00443 fuser = fi->fuser[fi->i]; 00444 /*@=boundsread@*/ 00445 } 00446 return fuser; 00447 } 00448 00449 const char * rpmfiFGroup(rpmfi fi) 00450 { 00451 const char * fgroup = NULL; 00452 00453 /* XXX add support for ancient RPMTAG_FILEGIDS? */ 00454 if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) { 00455 /*@-boundsread@*/ 00456 if (fi->fgroup != NULL) 00457 fgroup = fi->fgroup[fi->i]; 00458 /*@=boundsread@*/ 00459 } 00460 return fgroup; 00461 } 00462 00463 int rpmfiNext(rpmfi fi) 00464 { 00465 int i = -1; 00466 00467 if (fi != NULL && ++fi->i >= 0) { 00468 if (fi->i < fi->fc) { 00469 i = fi->i; 00470 /*@-boundsread@*/ 00471 if (fi->dil != NULL) 00472 fi->j = fi->dil[fi->i]; 00473 /*@=boundsread@*/ 00474 } else 00475 fi->i = -1; 00476 00477 /*@-modfilesys @*/ 00478 if (_rpmfi_debug < 0 && i != -1) 00479 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] : "")); 00480 /*@=modfilesys @*/ 00481 00482 } 00483 00484 return i; 00485 } 00486 00487 rpmfi rpmfiInit(rpmfi fi, int fx) 00488 { 00489 if (fi != NULL) { 00490 if (fx >= 0 && fx < fi->fc) { 00491 fi->i = fx - 1; 00492 fi->j = -1; 00493 } 00494 } 00495 00496 /*@-refcounttrans@*/ 00497 return fi; 00498 /*@=refcounttrans@*/ 00499 } 00500 00501 int rpmfiNextD(rpmfi fi) 00502 { 00503 int j = -1; 00504 00505 if (fi != NULL && ++fi->j >= 0) { 00506 if (fi->j < fi->dc) 00507 j = fi->j; 00508 else 00509 fi->j = -1; 00510 00511 /*@-modfilesys @*/ 00512 if (_rpmfi_debug < 0 && j != -1) 00513 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, (fi->Type ? fi->Type : "?Type?"), j); 00514 /*@=modfilesys @*/ 00515 00516 } 00517 00518 return j; 00519 } 00520 00521 rpmfi rpmfiInitD(rpmfi fi, int dx) 00522 { 00523 if (fi != NULL) { 00524 if (dx >= 0 && dx < fi->fc) 00525 fi->j = dx - 1; 00526 else 00527 fi = NULL; 00528 } 00529 00530 /*@-refcounttrans@*/ 00531 return fi; 00532 /*@=refcounttrans@*/ 00533 } 00534 00540 static /*@observer@*/ 00541 const char * ftstring (fileTypes ft) 00542 /*@*/ 00543 { 00544 switch (ft) { 00545 case XDIR: return "directory"; 00546 case CDEV: return "char dev"; 00547 case BDEV: return "block dev"; 00548 case LINK: return "link"; 00549 case SOCK: return "sock"; 00550 case PIPE: return "fifo/pipe"; 00551 case REG: return "file"; 00552 default: return "unknown file type"; 00553 } 00554 /*@notreached@*/ 00555 } 00556 00557 fileTypes whatis(uint_16 mode) 00558 { 00559 if (S_ISDIR(mode)) return XDIR; 00560 if (S_ISCHR(mode)) return CDEV; 00561 if (S_ISBLK(mode)) return BDEV; 00562 if (S_ISLNK(mode)) return LINK; 00563 /*@-unrecog@*/ 00564 if (S_ISSOCK(mode)) return SOCK; 00565 /*@=unrecog@*/ 00566 if (S_ISFIFO(mode)) return PIPE; 00567 return REG; 00568 } 00569 00570 /*@-boundsread@*/ 00571 int rpmfiCompare(const rpmfi afi, const rpmfi bfi) 00572 /*@*/ 00573 { 00574 fileTypes awhat = whatis(rpmfiFMode(afi)); 00575 fileTypes bwhat = whatis(rpmfiFMode(bfi)); 00576 00577 if (awhat != bwhat) return 1; 00578 00579 if (awhat == LINK) { 00580 const char * alink = rpmfiFLink(afi); 00581 const char * blink = rpmfiFLink(bfi); 00582 if (alink == blink) return 0; 00583 if (alink == NULL) return 1; 00584 if (blink == NULL) return -1; 00585 return strcmp(alink, blink); 00586 } else if (awhat == REG) { 00587 int aalgo = 0; 00588 size_t alen = 0; 00589 const unsigned char * adigest = rpmfiDigest(afi, &aalgo, &alen); 00590 int balgo = 0; 00591 size_t blen = 0; 00592 const unsigned char * bdigest = rpmfiDigest(bfi, &balgo, &blen); 00593 /* XXX W2DO? changing file digest algo may break rpmfiCompare. */ 00594 if (!(aalgo == balgo && alen == blen)) 00595 return -1; 00596 if (adigest == bdigest) return 0; 00597 if (adigest == NULL) return 1; 00598 if (bdigest == NULL) return -1; 00599 return memcmp(adigest, bdigest, alen); 00600 } 00601 00602 return 0; 00603 } 00604 /*@=boundsread@*/ 00605 00606 /*@-boundsread@*/ 00607 fileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing) 00608 { 00609 const char * fn = rpmfiFN(nfi); 00610 int newFlags = rpmfiFFlags(nfi); 00611 char buffer[1024+1]; 00612 fileTypes dbWhat, newWhat, diskWhat; 00613 struct stat sb; 00614 int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE; 00615 00616 if (lstat(fn, &sb)) { 00617 /* 00618 * The file doesn't exist on the disk. Create it unless the new 00619 * package has marked it as missingok, or allfiles is requested. 00620 */ 00621 if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) { 00622 rpmMessage(RPMMESS_DEBUG, D_("%s skipped due to missingok flag\n"), 00623 fn); 00624 return FA_SKIP; 00625 } else { 00626 return FA_CREATE; 00627 } 00628 } 00629 00630 diskWhat = whatis((int_16)sb.st_mode); 00631 dbWhat = whatis(rpmfiFMode(ofi)); 00632 newWhat = whatis(rpmfiFMode(nfi)); 00633 00634 /* 00635 * RPM >= 2.3.10 shouldn't create config directories -- we'll ignore 00636 * them in older packages as well. 00637 */ 00638 if (newWhat == XDIR) 00639 return FA_CREATE; 00640 00641 if (diskWhat != newWhat && dbWhat != REG && dbWhat != LINK) 00642 return save; 00643 else if (newWhat != dbWhat && diskWhat != dbWhat) 00644 return save; 00645 else if (dbWhat != newWhat) 00646 return FA_CREATE; 00647 else if (dbWhat != LINK && dbWhat != REG) 00648 return FA_CREATE; 00649 00650 /* 00651 * This order matters - we'd prefer to CREATE the file if at all 00652 * possible in case something else (like the timestamp) has changed. 00653 */ 00654 memset(buffer, 0, sizeof(buffer)); 00655 if (dbWhat == REG) { 00656 int oalgo = 0; 00657 size_t olen = 0; 00658 const unsigned char * odigest; 00659 int nalgo = 0; 00660 size_t nlen = 0; 00661 const unsigned char * ndigest; 00662 odigest = rpmfiDigest(ofi, &oalgo, &olen); 00663 if (diskWhat == REG) { 00664 if (!(newFlags & RPMFILE_SPARSE)) 00665 if (dodigest(oalgo, fn, buffer, 0, NULL)) 00666 return FA_CREATE; /* assume file has been removed */ 00667 if (odigest && !memcmp(odigest, buffer, olen)) 00668 return FA_CREATE; /* unmodified config file, replace. */ 00669 } 00670 ndigest = rpmfiDigest(nfi, &nalgo, &nlen); 00671 /*@-nullpass@*/ 00672 if (odigest && ndigest && oalgo == nalgo && olen == nlen 00673 && !memcmp(odigest, ndigest, nlen)) 00674 return FA_SKIP; /* identical file, don't bother. */ 00675 /*@=nullpass@*/ 00676 } else /* dbWhat == LINK */ { 00677 const char * oFLink, * nFLink; 00678 oFLink = rpmfiFLink(ofi); 00679 if (diskWhat == LINK) { 00680 if (readlink(fn, buffer, sizeof(buffer) - 1) == -1) 00681 return FA_CREATE; /* assume file has been removed */ 00682 buffer[sizeof(buffer)-1] = '\0'; 00683 if (oFLink && !strcmp(oFLink, buffer)) 00684 return FA_CREATE; /* unmodified config file, replace. */ 00685 } 00686 nFLink = rpmfiFLink(nfi); 00687 /*@-nullpass@*/ 00688 if (oFLink && nFLink && !strcmp(oFLink, nFLink)) 00689 return FA_SKIP; /* identical file, don't bother. */ 00690 /*@=nullpass@*/ 00691 } 00692 00693 /* 00694 * The config file on the disk has been modified, but 00695 * the ones in the two packages are different. It would 00696 * be nice if RPM was smart enough to at least try and 00697 * merge the difference ala CVS, but... 00698 */ 00699 return save; 00700 } 00701 /*@=boundsread@*/ 00702 00703 /*@observer@*/ 00704 const char * rpmfiTypeString(rpmfi fi) 00705 { 00706 switch(rpmteType(fi->te)) { 00707 case TR_ADDED: return " install"; 00708 case TR_REMOVED: return " erase"; 00709 default: return "???"; 00710 } 00711 /*@noteached@*/ 00712 } 00713 00714 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00715 00725 /*@-bounds@*/ 00726 static 00727 Header relocateFileList(const rpmts ts, rpmfi fi, 00728 Header origH, fileAction * actions) 00729 /*@globals h_errno, rpmGlobalMacroContext @*/ 00730 /*@modifies ts, fi, origH, actions, rpmGlobalMacroContext @*/ 00731 { 00732 rpmte p = rpmtsRelocateElement(ts); 00733 HGE_t hge = fi->hge; 00734 HAE_t hae = fi->hae; 00735 HME_t hme = fi->hme; 00736 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData); 00737 static int _printed = 0; 00738 int allowBadRelocate = (rpmtsFilterFlags(ts) & RPMPROB_FILTER_FORCERELOCATE); 00739 rpmRelocation relocations = NULL; 00740 int numRelocations; 00741 const char ** validRelocations; 00742 rpmTagType validType; 00743 int numValid; 00744 const char ** baseNames; 00745 const char ** dirNames; 00746 int_32 * dirIndexes; 00747 int_32 * newDirIndexes; 00748 int_32 fileCount; 00749 int_32 dirCount; 00750 uint_32 mydColor = rpmExpandNumeric("%{?_autorelocate_dcolor}"); 00751 uint_32 * fFlags = NULL; 00752 uint_32 * fColors = NULL; 00753 uint_32 * dColors = NULL; 00754 uint_16 * fModes = NULL; 00755 Header h; 00756 int nrelocated = 0; 00757 int fileAlloced = 0; 00758 char * fn = NULL; 00759 int haveRelocatedFile = 0; 00760 int reldel = 0; 00761 int len; 00762 int i, j, xx; 00763 00764 if (!hge(origH, RPMTAG_PREFIXES, &validType, &validRelocations, &numValid)) 00765 numValid = 0; 00766 00767 assert(p != NULL); 00768 numRelocations = 0; 00769 if (p->relocs) 00770 while (p->relocs[numRelocations].newPath || 00771 p->relocs[numRelocations].oldPath) 00772 numRelocations++; 00773 00774 /* 00775 * If no relocations are specified (usually the case), then return the 00776 * original header. If there are prefixes, however, then INSTPREFIXES 00777 * should be added, but, since relocateFileList() can be called more 00778 * than once for the same header, don't bother if already present. 00779 */ 00780 if (p->relocs == NULL || numRelocations == 0) { 00781 if (numValid) { 00782 if (!headerIsEntry(origH, RPMTAG_INSTPREFIXES)) 00783 xx = hae(origH, RPMTAG_INSTPREFIXES, 00784 validType, validRelocations, numValid); 00785 validRelocations = hfd(validRelocations, validType); 00786 } 00787 /* XXX FIXME multilib file actions need to be checked. */ 00788 return headerLink(origH); 00789 } 00790 00791 h = headerLink(origH); 00792 00793 relocations = alloca(sizeof(*relocations) * numRelocations); 00794 00795 /* Build sorted relocation list from raw relocations. */ 00796 for (i = 0; i < numRelocations; i++) { 00797 char * t; 00798 00799 /* 00800 * Default relocations (oldPath == NULL) are handled in the UI, 00801 * not rpmlib. 00802 */ 00803 if (p->relocs[i].oldPath == NULL) continue; /* XXX can't happen */ 00804 00805 /* FIXME: Trailing /'s will confuse us greatly. Internal ones will 00806 too, but those are more trouble to fix up. :-( */ 00807 t = alloca_strdup(p->relocs[i].oldPath); 00808 /*@-branchstate@*/ 00809 relocations[i].oldPath = (t[0] == '/' && t[1] == '\0') 00810 ? t 00811 : stripTrailingChar(t, '/'); 00812 /*@=branchstate@*/ 00813 00814 /* An old path w/o a new path is valid, and indicates exclusion */ 00815 if (p->relocs[i].newPath) { 00816 int del; 00817 00818 t = alloca_strdup(p->relocs[i].newPath); 00819 /*@-branchstate@*/ 00820 relocations[i].newPath = (t[0] == '/' && t[1] == '\0') 00821 ? t 00822 : stripTrailingChar(t, '/'); 00823 /*@=branchstate@*/ 00824 00825 /*@-nullpass@*/ /* FIX: relocations[i].oldPath == NULL */ 00826 /* Verify that the relocation's old path is in the header. */ 00827 for (j = 0; j < numValid; j++) { 00828 if (!strcmp(validRelocations[j], relocations[i].oldPath)) 00829 /*@innerbreak@*/ break; 00830 } 00831 00832 /* XXX actions check prevents problem from being appended twice. */ 00833 if (j == numValid && !allowBadRelocate && actions) { 00834 rpmps ps = rpmtsProblems(ts); 00835 rpmpsAppend(ps, RPMPROB_BADRELOCATE, 00836 rpmteNEVR(p), rpmteKey(p), 00837 relocations[i].oldPath, NULL, NULL, 0); 00838 ps = rpmpsFree(ps); 00839 } 00840 del = 00841 strlen(relocations[i].newPath) - strlen(relocations[i].oldPath); 00842 /*@=nullpass@*/ 00843 00844 if (del > reldel) 00845 reldel = del; 00846 } else { 00847 relocations[i].newPath = NULL; 00848 } 00849 } 00850 00851 /* stupid bubble sort, but it's probably faster here */ 00852 for (i = 0; i < numRelocations; i++) { 00853 int madeSwap; 00854 madeSwap = 0; 00855 for (j = 1; j < numRelocations; j++) { 00856 struct rpmRelocation_s tmpReloc; 00857 if (relocations[j - 1].oldPath == NULL || /* XXX can't happen */ 00858 relocations[j ].oldPath == NULL || /* XXX can't happen */ 00859 strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0) 00860 /*@innercontinue@*/ continue; 00861 /*@-usereleased@*/ /* LCL: ??? */ 00862 tmpReloc = relocations[j - 1]; 00863 relocations[j - 1] = relocations[j]; 00864 relocations[j] = tmpReloc; 00865 /*@=usereleased@*/ 00866 madeSwap = 1; 00867 } 00868 if (!madeSwap) break; 00869 } 00870 00871 if (!_printed) { 00872 _printed = 1; 00873 rpmMessage(RPMMESS_DEBUG, D_("========== relocations\n")); 00874 for (i = 0; i < numRelocations; i++) { 00875 if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */ 00876 if (relocations[i].newPath == NULL) 00877 rpmMessage(RPMMESS_DEBUG, D_("%5d exclude %s\n"), 00878 i, relocations[i].oldPath); 00879 else 00880 rpmMessage(RPMMESS_DEBUG, D_("%5d relocate %s -> %s\n"), 00881 i, relocations[i].oldPath, relocations[i].newPath); 00882 } 00883 } 00884 00885 /* Add relocation values to the header */ 00886 if (numValid) { 00887 const char ** actualRelocations; 00888 int numActual; 00889 00890 actualRelocations = xmalloc(numValid * sizeof(*actualRelocations)); 00891 numActual = 0; 00892 for (i = 0; i < numValid; i++) { 00893 for (j = 0; j < numRelocations; j++) { 00894 if (relocations[j].oldPath == NULL || /* XXX can't happen */ 00895 strcmp(validRelocations[i], relocations[j].oldPath)) 00896 /*@innercontinue@*/ continue; 00897 /* On install, a relocate to NULL means skip the path. */ 00898 if (relocations[j].newPath) { 00899 actualRelocations[numActual] = relocations[j].newPath; 00900 numActual++; 00901 } 00902 /*@innerbreak@*/ break; 00903 } 00904 if (j == numRelocations) { 00905 actualRelocations[numActual] = validRelocations[i]; 00906 numActual++; 00907 } 00908 } 00909 00910 if (numActual) 00911 xx = hae(h, RPMTAG_INSTPREFIXES, RPM_STRING_ARRAY_TYPE, 00912 (void **) actualRelocations, numActual); 00913 00914 actualRelocations = _free(actualRelocations); 00915 validRelocations = hfd(validRelocations, validType); 00916 } 00917 00918 xx = hge(h, RPMTAG_BASENAMES, NULL, &baseNames, &fileCount); 00919 xx = hge(h, RPMTAG_DIRINDEXES, NULL, &dirIndexes, NULL); 00920 xx = hge(h, RPMTAG_DIRNAMES, NULL, &dirNames, &dirCount); 00921 xx = hge(h, RPMTAG_FILEFLAGS, NULL, &fFlags, NULL); 00922 xx = hge(h, RPMTAG_FILECOLORS, NULL, &fColors, NULL); 00923 xx = hge(h, RPMTAG_FILEMODES, NULL, &fModes, NULL); 00924 00925 dColors = alloca(dirCount * sizeof(*dColors)); 00926 memset(dColors, 0, dirCount * sizeof(*dColors)); 00927 00928 newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount); 00929 memcpy(newDirIndexes, dirIndexes, sizeof(*newDirIndexes) * fileCount); 00930 dirIndexes = newDirIndexes; 00931 00932 /* 00933 * For all relocations, we go through sorted file/relocation lists 00934 * backwards so that /usr/local relocations take precedence over /usr 00935 * ones. 00936 */ 00937 00938 /* Relocate individual paths. */ 00939 00940 for (i = fileCount - 1; i >= 0; i--) { 00941 fileTypes ft; 00942 int fnlen; 00943 00944 len = reldel + 00945 strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1; 00946 /*@-branchstate@*/ 00947 if (len >= fileAlloced) { 00948 fileAlloced = len * 2; 00949 fn = xrealloc(fn, fileAlloced); 00950 } 00951 /*@=branchstate@*/ 00952 00953 assert(fn != NULL); /* XXX can't happen */ 00954 *fn = '\0'; 00955 fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn; 00956 00957 if (fColors != NULL) { 00958 /* XXX pkgs may not have unique dirNames, so color all dirNames that match. */ 00959 for (j = 0; j < dirCount; j++) { 00960 if (strcmp(dirNames[dirIndexes[i]], dirNames[j])) /*@innercontinue@*/ continue; 00961 dColors[j] |= fColors[i]; 00962 } 00963 } 00964 00965 /* 00966 * See if this file path needs relocating. 00967 */ 00968 /* 00969 * XXX FIXME: Would a bsearch of the (already sorted) 00970 * relocation list be a good idea? 00971 */ 00972 for (j = numRelocations - 1; j >= 0; j--) { 00973 if (relocations[j].oldPath == NULL) /* XXX can't happen */ 00974 /*@innercontinue@*/ continue; 00975 len = strcmp(relocations[j].oldPath, "/") 00976 ? strlen(relocations[j].oldPath) 00977 : 0; 00978 00979 if (fnlen < len) 00980 /*@innercontinue@*/ continue; 00981 /* 00982 * Only subdirectories or complete file paths may be relocated. We 00983 * don't check for '\0' as our directory names all end in '/'. 00984 */ 00985 if (!(fn[len] == '/' || fnlen == len)) 00986 /*@innercontinue@*/ continue; 00987 00988 if (strncmp(relocations[j].oldPath, fn, len)) 00989 /*@innercontinue@*/ continue; 00990 /*@innerbreak@*/ break; 00991 } 00992 if (j < 0) continue; 00993 00994 /*@-nullderef@*/ /* FIX: fModes may be NULL */ 00995 ft = whatis(fModes[i]); 00996 /*@=nullderef@*/ 00997 00998 /* On install, a relocate to NULL means skip the path. */ 00999 if (relocations[j].newPath == NULL) { 01000 if (ft == XDIR) { 01001 /* Start with the parent, looking for directory to exclude. */ 01002 for (j = dirIndexes[i]; j < dirCount; j++) { 01003 len = strlen(dirNames[j]) - 1; 01004 while (len > 0 && dirNames[j][len-1] == '/') len--; 01005 if (fnlen != len) 01006 /*@innercontinue@*/ continue; 01007 if (strncmp(fn, dirNames[j], fnlen)) 01008 /*@innercontinue@*/ continue; 01009 /*@innerbreak@*/ break; 01010 } 01011 } 01012 if (actions) { 01013 actions[i] = FA_SKIPNSTATE; 01014 rpmMessage(RPMMESS_DEBUG, D_("excluding %s %s\n"), 01015 ftstring(ft), fn); 01016 } 01017 continue; 01018 } 01019 01020 /* Relocation on full paths only, please. */ 01021 if (fnlen != len) continue; 01022 01023 if (actions) 01024 rpmMessage(RPMMESS_DEBUG, D_("relocating %s to %s\n"), 01025 fn, relocations[j].newPath); 01026 nrelocated++; 01027 01028 strcpy(fn, relocations[j].newPath); 01029 { char * te = strrchr(fn, '/'); 01030 if (te) { 01031 if (te > fn) te++; /* root is special */ 01032 fnlen = te - fn; 01033 } else 01034 te = fn + strlen(fn); 01035 /*@-nullpass -nullderef@*/ /* LCL: te != NULL here. */ 01036 if (strcmp(baseNames[i], te)) /* basename changed too? */ 01037 baseNames[i] = alloca_strdup(te); 01038 *te = '\0'; /* terminate new directory name */ 01039 /*@=nullpass =nullderef@*/ 01040 } 01041 01042 /* Does this directory already exist in the directory list? */ 01043 for (j = 0; j < dirCount; j++) { 01044 if (fnlen != strlen(dirNames[j])) 01045 /*@innercontinue@*/ continue; 01046 if (strncmp(fn, dirNames[j], fnlen)) 01047 /*@innercontinue@*/ continue; 01048 /*@innerbreak@*/ break; 01049 } 01050 01051 if (j < dirCount) { 01052 dirIndexes[i] = j; 01053 continue; 01054 } 01055 01056 /* Creating new paths is a pita */ 01057 if (!haveRelocatedFile) { 01058 const char ** newDirList; 01059 01060 haveRelocatedFile = 1; 01061 newDirList = xmalloc((dirCount + 1) * sizeof(*newDirList)); 01062 for (j = 0; j < dirCount; j++) 01063 newDirList[j] = alloca_strdup(dirNames[j]); 01064 dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE); 01065 dirNames = newDirList; 01066 } else { 01067 dirNames = xrealloc(dirNames, 01068 sizeof(*dirNames) * (dirCount + 1)); 01069 } 01070 01071 dirNames[dirCount] = alloca_strdup(fn); 01072 dirIndexes[i] = dirCount; 01073 dirCount++; 01074 } 01075 01076 /* Finish off by relocating directories. */ 01077 for (i = dirCount - 1; i >= 0; i--) { 01078 for (j = numRelocations - 1; j >= 0; j--) { 01079 01080 /* XXX Don't autorelocate uncolored directories. */ 01081 if (j == p->autorelocatex 01082 && (dColors[i] == 0 || !(dColors[i] & mydColor))) 01083 /*@innercontinue@*/ continue; 01084 01085 if (relocations[j].oldPath == NULL) /* XXX can't happen */ 01086 /*@innercontinue@*/ continue; 01087 len = strcmp(relocations[j].oldPath, "/") 01088 ? strlen(relocations[j].oldPath) 01089 : 0; 01090 01091 if (len && strncmp(relocations[j].oldPath, dirNames[i], len)) 01092 /*@innercontinue@*/ continue; 01093 01094 /* 01095 * Only subdirectories or complete file paths may be relocated. We 01096 * don't check for '\0' as our directory names all end in '/'. 01097 */ 01098 if (dirNames[i][len] != '/') 01099 /*@innercontinue@*/ continue; 01100 01101 if (relocations[j].newPath) { /* Relocate the path */ 01102 const char * s = relocations[j].newPath; 01103 char * t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1); 01104 size_t slen; 01105 01106 (void) stpcpy( stpcpy(t, s) , dirNames[i] + len); 01107 01108 /* Unfortunatly rpmCleanPath strips the trailing slash.. */ 01109 (void) rpmCleanPath(t); 01110 slen = strlen(t); 01111 t[slen] = '/'; 01112 t[slen+1] = '\0'; 01113 01114 if (actions) 01115 rpmMessage(RPMMESS_DEBUG, 01116 D_("relocating directory %s to %s\n"), dirNames[i], t); 01117 dirNames[i] = t; 01118 nrelocated++; 01119 } 01120 } 01121 } 01122 01123 /* Save original filenames in header and replace (relocated) filenames. */ 01124 if (nrelocated) { 01125 int c; 01126 void * d; 01127 rpmTagType t; 01128 01129 d = NULL; 01130 xx = hge(h, RPMTAG_BASENAMES, &t, &d, &c); 01131 xx = hae(h, RPMTAG_ORIGBASENAMES, t, d, c); 01132 d = hfd(d, t); 01133 01134 d = NULL; 01135 xx = hge(h, RPMTAG_DIRNAMES, &t, &d, &c); 01136 xx = hae(h, RPMTAG_ORIGDIRNAMES, t, d, c); 01137 d = hfd(d, t); 01138 01139 d = NULL; 01140 xx = hge(h, RPMTAG_DIRINDEXES, &t, &d, &c); 01141 xx = hae(h, RPMTAG_ORIGDIRINDEXES, t, d, c); 01142 d = hfd(d, t); 01143 01144 xx = hme(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE, 01145 baseNames, fileCount); 01146 fi->bnl = hfd(fi->bnl, RPM_STRING_ARRAY_TYPE); 01147 xx = hge(h, RPMTAG_BASENAMES, NULL, &fi->bnl, &fi->fc); 01148 01149 xx = hme(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE, 01150 dirNames, dirCount); 01151 fi->dnl = hfd(fi->dnl, RPM_STRING_ARRAY_TYPE); 01152 xx = hge(h, RPMTAG_DIRNAMES, NULL, &fi->dnl, &fi->dc); 01153 01154 xx = hme(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, 01155 dirIndexes, fileCount); 01156 xx = hge(h, RPMTAG_DIRINDEXES, NULL, &fi->dil, NULL); 01157 } 01158 01159 baseNames = hfd(baseNames, RPM_STRING_ARRAY_TYPE); 01160 dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE); 01161 /*@-dependenttrans@*/ 01162 fn = _free(fn); 01163 /*@=dependenttrans@*/ 01164 01165 return h; 01166 } 01167 /*@=bounds@*/ 01168 01169 rpmfi rpmfiFree(rpmfi fi) 01170 { 01171 HFD_t hfd = headerFreeData; 01172 01173 if (fi == NULL) return NULL; 01174 01175 if (fi->nrefs > 1) 01176 return rpmfiUnlink(fi, fi->Type); 01177 01178 /*@-modfilesys@*/ 01179 if (_rpmfi_debug < 0) 01180 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, fi->Type, fi->fc); 01181 /*@=modfilesys@*/ 01182 01183 /* Free pre- and post-transaction script and interpreter strings. */ 01184 fi->pretrans = _free(fi->pretrans); 01185 fi->pretransprog = _free(fi->pretransprog); 01186 fi->posttrans = _free(fi->posttrans); 01187 fi->posttransprog = _free(fi->posttransprog); 01188 01189 /*@-branchstate@*/ 01190 if (fi->fc > 0) { 01191 fi->bnl = hfd(fi->bnl, -1); 01192 fi->dnl = hfd(fi->dnl, -1); 01193 01194 fi->flinks = hfd(fi->flinks, -1); 01195 fi->flangs = hfd(fi->flangs, -1); 01196 fi->fdigests = hfd(fi->fdigests, -1); 01197 fi->digests = _free(fi->digests); 01198 01199 fi->cdict = hfd(fi->cdict, -1); 01200 01201 fi->fuser = hfd(fi->fuser, -1); 01202 fi->fgroup = hfd(fi->fgroup, -1); 01203 01204 fi->fstates = _free(fi->fstates); 01205 01206 /*@-evalorder@*/ 01207 if (!fi->keep_header && fi->h == NULL) { 01208 fi->fmtimes = _free(fi->fmtimes); 01209 fi->fmodes = _free(fi->fmodes); 01210 fi->fflags = _free(fi->fflags); 01211 fi->vflags = _free(fi->vflags); 01212 fi->fsizes = _free(fi->fsizes); 01213 fi->frdevs = _free(fi->frdevs); 01214 fi->finodes = _free(fi->finodes); 01215 fi->dil = _free(fi->dil); 01216 01217 fi->fcolors = _free(fi->fcolors); 01218 fi->fcdictx = _free(fi->fcdictx); 01219 fi->ddict = _free(fi->ddict); 01220 fi->fddictx = _free(fi->fddictx); 01221 fi->fddictn = _free(fi->fddictn); 01222 01223 } 01224 /*@=evalorder@*/ 01225 } 01226 /*@=branchstate@*/ 01227 01228 fi->fsm = freeFSM(fi->fsm); 01229 01230 fi->fn = _free(fi->fn); 01231 fi->apath = _free(fi->apath); 01232 fi->fmapflags = _free(fi->fmapflags); 01233 01234 fi->obnl = hfd(fi->obnl, -1); 01235 fi->odnl = hfd(fi->odnl, -1); 01236 01237 fi->fcontexts = hfd(fi->fcontexts, -1); 01238 01239 fi->actions = _free(fi->actions); 01240 fi->replacedSizes = _free(fi->replacedSizes); 01241 fi->replaced = _free(fi->replaced); 01242 01243 fi->h = headerFree(fi->h); 01244 01245 /*@-nullstate -refcounttrans -usereleased@*/ 01246 (void) rpmfiUnlink(fi, fi->Type); 01247 memset(fi, 0, sizeof(*fi)); /* XXX trash and burn */ 01248 fi = _free(fi); 01249 /*@=nullstate =refcounttrans =usereleased@*/ 01250 01251 return NULL; 01252 } 01253 01259 static inline unsigned char nibble(char c) 01260 /*@*/ 01261 { 01262 if (c >= '0' && c <= '9') 01263 return (c - '0'); 01264 if (c >= 'A' && c <= 'F') 01265 return (c - 'A') + 10; 01266 if (c >= 'a' && c <= 'f') 01267 return (c - 'a') + 10; 01268 return 0; 01269 } 01270 01271 #define _fdupe(_fi, _data) \ 01272 if ((_fi)->_data != NULL) \ 01273 (_fi)->_data = memcpy(xmalloc((_fi)->fc * sizeof(*(_fi)->_data)), \ 01274 (_fi)->_data, (_fi)->fc * sizeof(*(_fi)->_data)) 01275 01276 /* XXX Ick, not SEF. */ 01277 #define _fdupestring(_h, _tag, _data) \ 01278 if (hge((_h), (_tag), NULL, &(_data), NULL)) \ 01279 _data = xstrdup(_data) 01280 01281 rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, int flags) 01282 { 01283 HFD_t hfd = headerFreeData; 01284 int scareMem = (flags & 0x1); 01285 HGE_t hge = 01286 (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry); 01287 rpmte p; 01288 rpmfi fi = NULL; 01289 const char * Type; 01290 uint_32 * uip; 01291 int dnlmax, bnlmax; 01292 unsigned char * t; 01293 int len; 01294 int xx; 01295 int i; 01296 01297 #ifdef NOTYET /* XXX transaction.c still needs scareMem 1 */ 01298 assert(scareMem == 0); /* XXX always allocate memory */ 01299 #endif 01300 if (tagN == RPMTAG_BASENAMES) { 01301 Type = "Files"; 01302 } else { 01303 Type = "?Type?"; 01304 goto exit; 01305 } 01306 01307 fi = xcalloc(1, sizeof(*fi)); 01308 if (fi == NULL) /* XXX can't happen */ 01309 goto exit; 01310 01311 fi->magic = RPMFIMAGIC; 01312 fi->Type = Type; 01313 fi->i = -1; 01314 fi->tagN = tagN; 01315 01316 fi->hge = hge; 01317 fi->hae = (HAE_t) headerAddEntry; 01318 fi->hme = (HME_t) headerModifyEntry; 01319 fi->hre = (HRE_t) headerRemoveEntry; 01320 fi->hfd = headerFreeData; 01321 01322 fi->h = (h != NULL && scareMem ? headerLink(h) : NULL); 01323 01324 if (fi->fsm == NULL) 01325 fi->fsm = newFSM(); 01326 01327 fi->fsm->repackaged = (headerIsEntry(h, RPMTAG_REMOVETID) ? 1 : 0); 01328 01329 /* 0 means unknown */ 01330 xx = hge(h, RPMTAG_ARCHIVESIZE, NULL, &uip, NULL); 01331 fi->archivePos = 0; 01332 fi->archiveSize = (xx ? *uip : 0); 01333 01334 /* Extract pre- and post-transaction script and interpreter strings. */ 01335 _fdupestring(h, RPMTAG_PRETRANS, fi->pretrans); 01336 _fdupestring(h, RPMTAG_PRETRANSPROG, fi->pretransprog); 01337 _fdupestring(h, RPMTAG_POSTTRANS, fi->posttrans); 01338 _fdupestring(h, RPMTAG_POSTTRANSPROG, fi->posttransprog); 01339 01340 if (!hge(h, RPMTAG_BASENAMES, NULL, &fi->bnl, &fi->fc)) { 01341 fi->fc = 0; 01342 fi->dc = 0; 01343 goto exit; 01344 } 01345 xx = hge(h, RPMTAG_DIRNAMES, NULL, &fi->dnl, &fi->dc); 01346 xx = hge(h, RPMTAG_DIRINDEXES, NULL, &fi->dil, NULL); 01347 xx = hge(h, RPMTAG_FILEMODES, NULL, &fi->fmodes, NULL); 01348 xx = hge(h, RPMTAG_FILEFLAGS, NULL, &fi->fflags, NULL); 01349 xx = hge(h, RPMTAG_FILEVERIFYFLAGS, NULL, &fi->vflags, NULL); 01350 xx = hge(h, RPMTAG_FILESIZES, NULL, &fi->fsizes, NULL); 01351 01352 xx = hge(h, RPMTAG_FILECOLORS, NULL, &fi->fcolors, NULL); 01353 fi->color = 0; 01354 if (fi->fcolors != NULL) 01355 for (i = 0; i < fi->fc; i++) 01356 fi->color |= fi->fcolors[i]; 01357 xx = hge(h, RPMTAG_CLASSDICT, NULL, &fi->cdict, &fi->ncdict); 01358 xx = hge(h, RPMTAG_FILECLASS, NULL, &fi->fcdictx, NULL); 01359 01360 xx = hge(h, RPMTAG_DEPENDSDICT, NULL, &fi->ddict, &fi->nddict); 01361 xx = hge(h, RPMTAG_FILEDEPENDSX, NULL, &fi->fddictx, NULL); 01362 xx = hge(h, RPMTAG_FILEDEPENDSN, NULL, &fi->fddictn, NULL); 01363 01364 xx = hge(h, RPMTAG_FILESTATES, NULL, &fi->fstates, NULL); 01365 if (xx == 0 || fi->fstates == NULL) 01366 fi->fstates = xcalloc(fi->fc, sizeof(*fi->fstates)); 01367 else 01368 _fdupe(fi, fstates); 01369 01370 fi->action = FA_UNKNOWN; 01371 fi->flags = 0; 01372 01373 if (fi->actions == NULL) 01374 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions)); 01375 01376 fi->keep_header = (scareMem ? 1 : 0); 01377 01378 /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */ 01379 fi->mapflags = 01380 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID; 01381 01382 xx = hge(h, RPMTAG_FILELINKTOS, NULL, &fi->flinks, NULL); 01383 xx = hge(h, RPMTAG_FILELANGS, NULL, &fi->flangs, NULL); 01384 01385 fi->digestalgo = PGPHASHALGO_MD5; 01386 fi->digestlen = 16; 01387 fi->fdigestalgos = NULL; 01388 xx = hge(h, RPMTAG_FILEDIGESTALGOS, NULL, &fi->fdigestalgos, NULL); 01389 if (fi->fdigestalgos) { 01390 int dalgo = 0; 01391 /* XXX Insure that all algorithms are either 0 or constant. */ 01392 for (i = 0; i < fi->fc; i++) { 01393 if (fi->fdigestalgos[i] == 0) 01394 continue; 01395 if (dalgo == 0) 01396 dalgo = fi->fdigestalgos[i]; 01397 else 01398 assert(dalgo == fi->fdigestalgos[i]); 01399 } 01400 fi->digestalgo = dalgo; 01401 switch (dalgo) { 01402 case PGPHASHALGO_MD5: fi->digestlen = 128/8; break; 01403 case PGPHASHALGO_SHA1: fi->digestlen = 160/8; break; 01404 case PGPHASHALGO_RIPEMD128: fi->digestlen = 128/8; break; 01405 case PGPHASHALGO_RIPEMD160: fi->digestlen = 160/8; break; 01406 case PGPHASHALGO_SHA256: fi->digestlen = 256/8; break; 01407 case PGPHASHALGO_SHA384: fi->digestlen = 384/8; break; 01408 case PGPHASHALGO_SHA512: fi->digestlen = 512/8; break; 01409 case PGPHASHALGO_CRC32: fi->digestlen = 32/8; break; 01410 } 01411 fi->fdigestalgos = NULL; 01412 } 01413 01414 fi->fdigests = NULL; 01415 xx = hge(h, RPMTAG_FILEDIGESTS, NULL, &fi->fdigests, NULL); 01416 01417 fi->digests = NULL; 01418 if (fi->fdigests) { 01419 t = xmalloc(fi->fc * fi->digestlen); 01420 fi->digests = t; 01421 for (i = 0; i < fi->fc; i++) { 01422 const char * fdigests; 01423 int j; 01424 01425 fdigests = fi->fdigests[i]; 01426 if (!(fdigests && *fdigests != '\0')) { 01427 memset(t, 0, fi->digestlen); 01428 t += fi->digestlen; 01429 continue; 01430 } 01431 for (j = 0; j < fi->digestlen; j++, t++, fdigests += 2) 01432 *t = (nibble(fdigests[0]) << 4) | nibble(fdigests[1]); 01433 } 01434 fi->fdigests = hfd(fi->fdigests, -1); 01435 } 01436 01437 /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes, or fcontexts */ 01438 xx = hge(h, RPMTAG_FILEMTIMES, NULL, &fi->fmtimes, NULL); 01439 xx = hge(h, RPMTAG_FILERDEVS, NULL, &fi->frdevs, NULL); 01440 xx = hge(h, RPMTAG_FILEINODES, NULL, &fi->finodes, NULL); 01441 xx = hge(h, RPMTAG_FILECONTEXTS, NULL, &fi->fcontexts, NULL); 01442 01443 fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes)); 01444 01445 xx = hge(h, RPMTAG_FILEUSERNAME, NULL, &fi->fuser, NULL); 01446 xx = hge(h, RPMTAG_FILEGROUPNAME, NULL, &fi->fgroup, NULL); 01447 01448 if (ts != NULL) 01449 if (fi != NULL) 01450 if ((p = rpmtsRelocateElement(ts)) != NULL && rpmteType(p) == TR_ADDED 01451 && headerIsEntry(h, RPMTAG_SOURCERPM) 01452 && !headerIsEntry(h, RPMTAG_ORIGBASENAMES)) 01453 { 01454 const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL); 01455 const char * errstr; 01456 char * newPath; 01457 Header foo; 01458 01459 /* XXX error handling. */ 01460 newPath = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr); 01461 fmt = _free(fmt); 01462 01463 #if __ia64__ 01464 /* XXX On ia64, change leading /emul/ix86 -> /emul/ia32, ick. */ 01465 if (newPath != NULL && *newPath != '\0' 01466 && strlen(newPath) >= (sizeof("/emul/i386")-1) 01467 && newPath[0] == '/' && newPath[1] == 'e' && newPath[2] == 'm' 01468 && newPath[3] == 'u' && newPath[4] == 'l' && newPath[5] == '/' 01469 && newPath[6] == 'i' && newPath[8] == '8' && newPath[9] == '6') 01470 { 01471 newPath[7] = 'a'; 01472 newPath[8] = '3'; 01473 newPath[9] = '2'; 01474 } 01475 #endif 01476 01477 /* XXX Make sure autoreloc is not already specified. */ 01478 i = p->nrelocs; 01479 if (newPath != NULL && *newPath != '\0' && p->relocs != NULL) 01480 for (i = 0; i < p->nrelocs; i++) { 01481 /*@-nullpass@*/ /* XXX {old,new}Path might be NULL */ 01482 if (strcmp(p->relocs[i].oldPath, "/")) 01483 continue; 01484 if (strcmp(p->relocs[i].newPath, newPath)) 01485 continue; 01486 /*@=nullpass@*/ 01487 break; 01488 } 01489 01490 /* XXX test for incompatible arch triggering autorelocation is dumb. */ 01491 /* XXX DIEDIEDIE: used to test '... && p->archScore == 0' */ 01492 if (newPath != NULL && *newPath != '\0' && i == p->nrelocs) { 01493 01494 p->relocs = 01495 xrealloc(p->relocs, (p->nrelocs + 2) * sizeof(*p->relocs)); 01496 p->relocs[p->nrelocs].oldPath = xstrdup("/"); 01497 p->relocs[p->nrelocs].newPath = xstrdup(newPath); 01498 p->autorelocatex = p->nrelocs; 01499 p->nrelocs++; 01500 p->relocs[p->nrelocs].oldPath = NULL; 01501 p->relocs[p->nrelocs].newPath = NULL; 01502 } 01503 newPath = _free(newPath); 01504 01505 /* XXX DYING */ 01506 if (fi->actions == NULL) 01507 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions)); 01508 /*@-compdef@*/ /* FIX: fi->digests undefined */ 01509 foo = relocateFileList(ts, fi, h, fi->actions); 01510 /*@=compdef@*/ 01511 fi->h = headerFree(fi->h); 01512 fi->h = headerLink(foo); 01513 foo = headerFree(foo); 01514 } 01515 01516 if (!scareMem) { 01517 _fdupe(fi, fmtimes); 01518 _fdupe(fi, frdevs); 01519 _fdupe(fi, finodes); 01520 _fdupe(fi, fsizes); 01521 _fdupe(fi, fflags); 01522 _fdupe(fi, vflags); 01523 _fdupe(fi, fmodes); 01524 _fdupe(fi, dil); 01525 01526 _fdupe(fi, fcolors); 01527 _fdupe(fi, fcdictx); 01528 01529 if (fi->ddict != NULL) 01530 fi->ddict = memcpy(xmalloc(fi->nddict * sizeof(*fi->ddict)), 01531 fi->ddict, fi->nddict * sizeof(*fi->ddict)); 01532 01533 _fdupe(fi, fddictx); 01534 _fdupe(fi, fddictn); 01535 01536 fi->h = headerFree(fi->h); 01537 } 01538 01539 dnlmax = -1; 01540 for (i = 0; i < fi->dc; i++) { 01541 if ((len = strlen(fi->dnl[i])) > dnlmax) 01542 dnlmax = len; 01543 } 01544 bnlmax = -1; 01545 for (i = 0; i < fi->fc; i++) { 01546 if ((len = strlen(fi->bnl[i])) > bnlmax) 01547 bnlmax = len; 01548 } 01549 fi->fnlen = dnlmax + bnlmax + 1; 01550 fi->fn = NULL; 01551 01552 fi->dperms = 0755; 01553 fi->fperms = 0644; 01554 01555 exit: 01556 /*@-modfilesys@*/ 01557 if (_rpmfi_debug < 0) 01558 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, Type, (fi ? fi->fc : 0)); 01559 /*@=modfilesys@*/ 01560 01561 /*@-compdef -nullstate@*/ /* FIX: rpmfi null annotations */ 01562 return rpmfiLink(fi, (fi ? fi->Type : NULL)); 01563 /*@=compdef =nullstate@*/ 01564 } 01565 01566 void rpmfiBuildFClasses(Header h, 01567 /*@out@*/ const char *** fclassp, /*@out@*/ int * fcp) 01568 { 01569 int scareMem = 0; 01570 rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem); 01571 const char * FClass; 01572 const char ** av; 01573 int ac; 01574 size_t nb; 01575 char * t; 01576 01577 if ((ac = rpmfiFC(fi)) <= 0) { 01578 av = NULL; 01579 ac = 0; 01580 goto exit; 01581 } 01582 01583 /* Compute size of file class argv array blob. */ 01584 nb = (ac + 1) * sizeof(*av); 01585 fi = rpmfiInit(fi, 0); 01586 if (fi != NULL) 01587 while (rpmfiNext(fi) >= 0) { 01588 FClass = rpmfiFClass(fi); 01589 if (FClass && *FClass != '\0') 01590 nb += strlen(FClass); 01591 nb += 1; 01592 } 01593 01594 /* Create and load file class argv array. */ 01595 av = xmalloc(nb); 01596 t = ((char *) av) + ((ac + 1) * sizeof(*av)); 01597 ac = 0; 01598 fi = rpmfiInit(fi, 0); 01599 if (fi != NULL) 01600 while (rpmfiNext(fi) >= 0) { 01601 FClass = rpmfiFClass(fi); 01602 av[ac++] = t; 01603 if (FClass && *FClass != '\0') 01604 t = stpcpy(t, FClass); 01605 *t++ = '\0'; 01606 } 01607 av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */ 01608 /*@=branchstate@*/ 01609 01610 exit: 01611 fi = rpmfiFree(fi); 01612 /*@-branchstate@*/ 01613 if (fclassp) 01614 *fclassp = av; 01615 else 01616 av = _free(av); 01617 /*@=branchstate@*/ 01618 if (fcp) *fcp = ac; 01619 } 01620 01621 void rpmfiBuildFContexts(Header h, 01622 /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp) 01623 { 01624 int scareMem = 0; 01625 rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem); 01626 const char * fcontext; 01627 const char ** av; 01628 int ac; 01629 size_t nb; 01630 char * t; 01631 01632 if ((ac = rpmfiFC(fi)) <= 0) { 01633 av = NULL; 01634 ac = 0; 01635 goto exit; 01636 } 01637 01638 /* Compute size of argv array blob. */ 01639 nb = (ac + 1) * sizeof(*av); 01640 fi = rpmfiInit(fi, 0); 01641 if (fi != NULL) 01642 while (rpmfiNext(fi) >= 0) { 01643 fcontext = rpmfiFContext(fi); 01644 if (fcontext && *fcontext != '\0') 01645 nb += strlen(fcontext); 01646 nb += 1; 01647 } 01648 01649 /* Create and load argv array. */ 01650 av = xmalloc(nb); 01651 t = ((char *) av) + ((ac + 1) * sizeof(*av)); 01652 ac = 0; 01653 fi = rpmfiInit(fi, 0); 01654 if (fi != NULL) 01655 while (rpmfiNext(fi) >= 0) { 01656 fcontext = rpmfiFContext(fi); 01657 av[ac++] = t; 01658 if (fcontext && *fcontext != '\0') 01659 t = stpcpy(t, fcontext); 01660 *t++ = '\0'; 01661 } 01662 av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */ 01663 /*@=branchstate@*/ 01664 01665 exit: 01666 fi = rpmfiFree(fi); 01667 /*@-branchstate@*/ 01668 if (fcontextp) 01669 *fcontextp = av; 01670 else 01671 av = _free(av); 01672 /*@=branchstate@*/ 01673 if (fcp) *fcp = ac; 01674 } 01675 01676 void rpmfiBuildFSContexts(Header h, 01677 /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp) 01678 { 01679 int scareMem = 0; 01680 rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem); 01681 const char ** av; 01682 int ac; 01683 size_t nb; 01684 char * t; 01685 char * fctxt = NULL; 01686 size_t fctxtlen = 0; 01687 int * fcnb; 01688 01689 if ((ac = rpmfiFC(fi)) <= 0) { 01690 av = NULL; 01691 ac = 0; 01692 goto exit; 01693 } 01694 01695 /* Compute size of argv array blob, concatenating file contexts. */ 01696 nb = ac * sizeof(*fcnb); 01697 fcnb = memset(alloca(nb), 0, nb); 01698 ac = 0; 01699 fi = rpmfiInit(fi, 0); 01700 if (fi != NULL) 01701 while (rpmfiNext(fi) >= 0) { 01702 const char * fn = rpmfiFN(fi); 01703 security_context_t scon; 01704 01705 fcnb[ac] = lgetfilecon(fn, &scon); 01706 /*@-branchstate@*/ 01707 if (fcnb[ac] > 0) { 01708 fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]); 01709 memcpy(fctxt+fctxtlen, scon, fcnb[ac]); 01710 fctxtlen += fcnb[ac]; 01711 freecon(scon); 01712 } 01713 /*@=branchstate@*/ 01714 ac++; 01715 } 01716 01717 /* Create and load argv array from concatenated file contexts. */ 01718 nb = (ac + 1) * sizeof(*av) + fctxtlen; 01719 av = xmalloc(nb); 01720 t = ((char *) av) + ((ac + 1) * sizeof(*av)); 01721 if (fctxt != NULL && fctxtlen > 0) 01722 (void) memcpy(t, fctxt, fctxtlen); 01723 ac = 0; 01724 fi = rpmfiInit(fi, 0); 01725 if (fi != NULL) 01726 while (rpmfiNext(fi) >= 0) { 01727 av[ac] = ""; 01728 if (fcnb[ac] > 0) { 01729 av[ac] = t; 01730 t += fcnb[ac]; 01731 } 01732 ac++; 01733 } 01734 av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */ 01735 01736 exit: 01737 fi = rpmfiFree(fi); 01738 /*@-branchstate@*/ 01739 if (fcontextp) 01740 *fcontextp = av; 01741 else 01742 av = _free(av); 01743 /*@=branchstate@*/ 01744 if (fcp) *fcp = ac; 01745 } 01746 01747 void rpmfiBuildREContexts(Header h, 01748 /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp) 01749 { 01750 int scareMem = 0; 01751 rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem); 01752 const char ** av = NULL; 01753 int ac; 01754 size_t nb; 01755 char * t; 01756 char * fctxt = NULL; 01757 size_t fctxtlen = 0; 01758 int * fcnb; 01759 01760 if ((ac = rpmfiFC(fi)) <= 0) { 01761 ac = 0; 01762 goto exit; 01763 } 01764 01765 /* Read security context patterns. */ 01766 { const char *fn = rpmGetPath("%{?__file_context_path}", NULL); 01767 if (fn != NULL && *fn != '\0') 01768 matchpathcon_init(fn); 01769 fn = _free(fn); 01770 } 01771 01772 /* Compute size of argv array blob, concatenating file contexts. */ 01773 nb = ac * sizeof(*fcnb); 01774 fcnb = memset(alloca(nb), 0, nb); 01775 ac = 0; 01776 fi = rpmfiInit(fi, 0); 01777 if (fi != NULL) 01778 while (rpmfiNext(fi) >= 0) { 01779 const char * fn = rpmfiFN(fi); 01780 mode_t fmode = rpmfiFMode(fi); 01781 security_context_t scon; 01782 01783 scon = NULL; 01784 if (matchpathcon(fn, fmode, &scon) == 0 && scon != NULL) { 01785 fcnb[ac] = strlen(scon) + 1; 01786 /*@-branchstate@*/ 01787 if (fcnb[ac] > 0) { 01788 fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]); 01789 memcpy(fctxt+fctxtlen, scon, fcnb[ac]); 01790 fctxtlen += fcnb[ac]; 01791 } 01792 /*@=branchstate@*/ 01793 freecon(scon); 01794 } 01795 ac++; 01796 } 01797 01798 /* Create and load argv array from concatenated file contexts. */ 01799 nb = (ac + 1) * sizeof(*av) + fctxtlen; 01800 av = xmalloc(nb); 01801 t = ((char *) av) + ((ac + 1) * sizeof(*av)); 01802 (void) memcpy(t, fctxt, fctxtlen); 01803 ac = 0; 01804 fi = rpmfiInit(fi, 0); 01805 if (fi != NULL) 01806 while (rpmfiNext(fi) >= 0) { 01807 av[ac] = ""; 01808 if (fcnb[ac] > 0) { 01809 av[ac] = t; 01810 t += fcnb[ac]; 01811 } 01812 ac++; 01813 } 01814 av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */ 01815 01816 exit: 01817 fi = rpmfiFree(fi); 01818 /*@-branchstate@*/ 01819 if (fcontextp) 01820 *fcontextp = av; 01821 else 01822 av = _free(av); 01823 /*@=branchstate@*/ 01824 if (fcp) *fcp = ac; 01825 } 01826 01827 void rpmfiBuildFDeps(Header h, rpmTag tagN, 01828 /*@out@*/ const char *** fdepsp, /*@out@*/ int * fcp) 01829 { 01830 int scareMem = 0; 01831 rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem); 01832 rpmds ds = NULL; 01833 const char ** av; 01834 int ac; 01835 size_t nb; 01836 char * t; 01837 char deptype = 'R'; 01838 char mydt; 01839 const char * DNEVR; 01840 const uint_32 * ddict; 01841 unsigned ix; 01842 int ndx; 01843 01844 if ((ac = rpmfiFC(fi)) <= 0) { 01845 av = NULL; 01846 ac = 0; 01847 goto exit; 01848 } 01849 01850 if (tagN == RPMTAG_PROVIDENAME) 01851 deptype = 'P'; 01852 else if (tagN == RPMTAG_REQUIRENAME) 01853 deptype = 'R'; 01854 01855 ds = rpmdsNew(h, tagN, scareMem); 01856 01857 /* Compute size of file depends argv array blob. */ 01858 nb = (ac + 1) * sizeof(*av); 01859 fi = rpmfiInit(fi, 0); 01860 if (fi != NULL) 01861 while (rpmfiNext(fi) >= 0) { 01862 ddict = NULL; 01863 ndx = rpmfiFDepends(fi, &ddict); 01864 if (ddict != NULL) 01865 while (ndx-- > 0) { 01866 ix = *ddict++; 01867 mydt = ((ix >> 24) & 0xff); 01868 if (mydt != deptype) 01869 /*@innercontinue@*/ continue; 01870 ix &= 0x00ffffff; 01871 (void) rpmdsSetIx(ds, ix-1); 01872 if (rpmdsNext(ds) < 0) 01873 /*@innercontinue@*/ continue; 01874 DNEVR = rpmdsDNEVR(ds); 01875 if (DNEVR != NULL) 01876 nb += strlen(DNEVR+2) + 1; 01877 } 01878 nb += 1; 01879 } 01880 01881 /* Create and load file depends argv array. */ 01882 av = xmalloc(nb); 01883 t = ((char *) av) + ((ac + 1) * sizeof(*av)); 01884 ac = 0; 01885 /*@-branchstate@*/ 01886 fi = rpmfiInit(fi, 0); 01887 if (fi != NULL) 01888 while (rpmfiNext(fi) >= 0) { 01889 av[ac++] = t; 01890 ddict = NULL; 01891 ndx = rpmfiFDepends(fi, &ddict); 01892 if (ddict != NULL) 01893 while (ndx-- > 0) { 01894 ix = *ddict++; 01895 mydt = ((ix >> 24) & 0xff); 01896 if (mydt != deptype) 01897 /*@innercontinue@*/ continue; 01898 ix &= 0x00ffffff; 01899 (void) rpmdsSetIx(ds, ix-1); 01900 if (rpmdsNext(ds) < 0) 01901 /*@innercontinue@*/ continue; 01902 DNEVR = rpmdsDNEVR(ds); 01903 if (DNEVR != NULL) { 01904 t = stpcpy(t, DNEVR+2); 01905 *t++ = ' '; 01906 *t = '\0'; 01907 } 01908 } 01909 *t++ = '\0'; 01910 } 01911 /*@=branchstate@*/ 01912 av[ac] = NULL; /* XXX tag arrays are not NULL terminated. */ 01913 01914 exit: 01915 fi = rpmfiFree(fi); 01916 ds = rpmdsFree(ds); 01917 /*@-branchstate@*/ 01918 if (fdepsp) 01919 *fdepsp = av; 01920 else 01921 av = _free(av); 01922 /*@=branchstate@*/ 01923 if (fcp) *fcp = ac; 01924 }