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