lib/rpmfi.c

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

Generated on Mon Mar 5 13:43:55 2007 for rpm by  doxygen 1.5.1