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

Generated on Thu Oct 25 09:23:14 2007 for rpm by  doxygen 1.5.1