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