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