Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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 "rpmsx.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 && dbWhat != REG && dbWhat != LINK)
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     if (dbWhat == REG) {
00595         const unsigned char * omd5, * nmd5;
00596         omd5 = rpmfiMD5(ofi);
00597         if (diskWhat == REG) {
00598             if (domd5(fn, (unsigned char *)buffer, 0, NULL))
00599                 return FA_CREATE; /* assume file has been removed */
00600             if (omd5 && !memcmp(omd5, buffer, 16))
00601                 return FA_CREATE; /* unmodified config file, replace. */
00602         }
00603         if (domd5(fn, buffer, 0, NULL))
00604             return FA_CREATE;   /* assume file has been removed */
00605         if (omd5 && !memcmp(omd5, buffer, 16))
00606             return FA_CREATE;   /* unmodified config file, replace. */
00607         nmd5 = rpmfiMD5(nfi);
00608 /*@-nullpass@*/
00609         if (omd5 && nmd5 && !memcmp(omd5, nmd5, 16))
00610             return FA_SKIP;     /* identical file, don't bother. */
00611 /*@=nullpass@*/
00612     } else /* dbWhat == LINK */ {
00613         const char * oFLink, * nFLink;
00614         memset(buffer, 0, sizeof(buffer));
00615         oFLink = rpmfiFLink(ofi);
00616         if (diskWhat == LINK) {
00617             if (readlink(fn, buffer, sizeof(buffer) - 1) == -1)
00618                 return FA_CREATE;       /* assume file has been removed */
00619             if (oFLink && !strcmp(oFLink, buffer))
00620                 return FA_CREATE;       /* unmodified config file, replace. */
00621         }
00622         nFLink = rpmfiFLink(nfi);
00623 /*@-nullpass@*/
00624         if (oFLink && nFLink && !strcmp(oFLink, nFLink))
00625             return FA_SKIP;     /* identical file, don't bother. */
00626 /*@=nullpass@*/
00627     }
00628 
00629     /*
00630      * The config file on the disk has been modified, but
00631      * the ones in the two packages are different. It would
00632      * be nice if RPM was smart enough to at least try and
00633      * merge the difference ala CVS, but...
00634      */
00635     return save;
00636 }
00637 /*@=boundsread@*/
00638 
00639 /*@-boundsread@*/
00640 int rpmfiConfigConflict(const rpmfi fi)
00641 {
00642     const char * fn = rpmfiFN(fi);
00643     int flags = rpmfiFFlags(fi);
00644     char buffer[1024];
00645     fileTypes newWhat, diskWhat;
00646     struct stat sb;
00647 
00648     if (!(flags & RPMFILE_CONFIG) || lstat(fn, &sb)) {
00649         return 0;
00650     }
00651 
00652     diskWhat = whatis((int_16)sb.st_mode);
00653     newWhat = whatis(rpmfiFMode(fi));
00654 
00655     if (newWhat != LINK && newWhat != REG)
00656         return 1;
00657 
00658     if (diskWhat != newWhat)
00659         return 1;
00660     
00661     memset(buffer, 0, sizeof(buffer));
00662     if (newWhat == REG) {
00663         const unsigned char * nmd5;
00664         if (domd5(fn, (unsigned char *)buffer, 0, NULL))
00665             return 0;   /* assume file has been removed */
00666         nmd5 = rpmfiMD5(fi);
00667         if (nmd5 && !memcmp(nmd5, buffer, 16))
00668             return 0;   /* unmodified config file */
00669     } else /* newWhat == LINK */ {
00670         const char * nFLink;
00671         if (readlink(fn, buffer, sizeof(buffer) - 1) == -1)
00672             return 0;   /* assume file has been removed */
00673         nFLink = rpmfiFLink(fi);
00674         if (nFLink && !strcmp(nFLink, buffer))
00675             return 0;   /* unmodified config file */
00676     }
00677 
00678     return 1;
00679 }
00680 /*@=boundsread@*/
00681 
00682 /*@observer@*/
00683 const char *const rpmfiTypeString(rpmfi fi)
00684 {
00685     switch(rpmteType(fi->te)) {
00686     case TR_ADDED:      return " install";
00687     case TR_REMOVED:    return "   erase";
00688     default:            return "???";
00689     }
00690     /*@noteached@*/
00691 }
00692 
00693 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
00694 
00704 /*@-bounds@*/
00705 static
00706 Header relocateFileList(const rpmts ts, rpmfi fi,
00707                 Header origH, fileAction * actions)
00708         /*@modifies ts, fi, origH, actions @*/
00709 {
00710     rpmte p = rpmtsRelocateElement(ts);
00711     HGE_t hge = fi->hge;
00712     HAE_t hae = fi->hae;
00713     HME_t hme = fi->hme;
00714     HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00715     static int _printed = 0;
00716     int allowBadRelocate = (rpmtsFilterFlags(ts) & RPMPROB_FILTER_FORCERELOCATE);
00717     rpmRelocation * relocations = NULL;
00718     int numRelocations;
00719     const char ** validRelocations;
00720     rpmTagType validType;
00721     int numValid;
00722     const char ** baseNames;
00723     const char ** dirNames;
00724     int_32 * dirIndexes;
00725     int_32 * newDirIndexes;
00726     int_32 fileCount;
00727     int_32 dirCount;
00728     uint_32 mydColor = rpmExpandNumeric("%{?_autorelocate_dcolor}");
00729     uint_32 * fFlags = NULL;
00730     uint_32 * fColors = NULL;
00731     uint_32 * dColors = NULL;
00732     uint_16 * fModes = NULL;
00733     Header h;
00734     int nrelocated = 0;
00735     int fileAlloced = 0;
00736     char * fn = NULL;
00737     int haveRelocatedFile = 0;
00738     int reldel = 0;
00739     int len;
00740     int i, j, xx;
00741 
00742     if (!hge(origH, RPMTAG_PREFIXES, &validType,
00743                         (void **) &validRelocations, &numValid))
00744         numValid = 0;
00745 
00746 assert(p != NULL);
00747     numRelocations = 0;
00748     if (p->relocs)
00749         while (p->relocs[numRelocations].newPath ||
00750                p->relocs[numRelocations].oldPath)
00751             numRelocations++;
00752 
00753     /*
00754      * If no relocations are specified (usually the case), then return the
00755      * original header. If there are prefixes, however, then INSTPREFIXES
00756      * should be added, but, since relocateFileList() can be called more
00757      * than once for the same header, don't bother if already present.
00758      */
00759     if (p->relocs == NULL || numRelocations == 0) {
00760         if (numValid) {
00761             if (!headerIsEntry(origH, RPMTAG_INSTPREFIXES))
00762                 xx = hae(origH, RPMTAG_INSTPREFIXES,
00763                         validType, validRelocations, numValid);
00764             validRelocations = hfd(validRelocations, validType);
00765         }
00766         /* XXX FIXME multilib file actions need to be checked. */
00767         return headerLink(origH);
00768     }
00769 
00770     h = headerLink(origH);
00771 
00772     relocations = alloca(sizeof(*relocations) * numRelocations);
00773 
00774     /* Build sorted relocation list from raw relocations. */
00775     for (i = 0; i < numRelocations; i++) {
00776         char * t;
00777 
00778         /*
00779          * Default relocations (oldPath == NULL) are handled in the UI,
00780          * not rpmlib.
00781          */
00782         if (p->relocs[i].oldPath == NULL) continue; /* XXX can't happen */
00783 
00784         /* FIXME: Trailing /'s will confuse us greatly. Internal ones will 
00785            too, but those are more trouble to fix up. :-( */
00786         t = alloca_strdup(p->relocs[i].oldPath);
00787         /*@-branchstate@*/
00788         relocations[i].oldPath = (t[0] == '/' && t[1] == '\0')
00789             ? t
00790             : stripTrailingChar(t, '/');
00791         /*@=branchstate@*/
00792 
00793         /* An old path w/o a new path is valid, and indicates exclusion */
00794         if (p->relocs[i].newPath) {
00795             int del;
00796 
00797             t = alloca_strdup(p->relocs[i].newPath);
00798             /*@-branchstate@*/
00799             relocations[i].newPath = (t[0] == '/' && t[1] == '\0')
00800                 ? t
00801                 : stripTrailingChar(t, '/');
00802             /*@=branchstate@*/
00803 
00804             /*@-nullpass@*/     /* FIX:  relocations[i].oldPath == NULL */
00805             /* Verify that the relocation's old path is in the header. */
00806             for (j = 0; j < numValid; j++) {
00807                 if (!strcmp(validRelocations[j], relocations[i].oldPath))
00808                     /*@innerbreak@*/ break;
00809             }
00810 
00811             /* XXX actions check prevents problem from being appended twice. */
00812             if (j == numValid && !allowBadRelocate && actions) {
00813                 rpmps ps = rpmtsProblems(ts);
00814                 rpmpsAppend(ps, RPMPROB_BADRELOCATE,
00815                         rpmteNEVR(p), rpmteKey(p),
00816                         relocations[i].oldPath, NULL, NULL, 0);
00817                 ps = rpmpsFree(ps);
00818             }
00819             del =
00820                 strlen(relocations[i].newPath) - strlen(relocations[i].oldPath);
00821             /*@=nullpass@*/
00822 
00823             if (del > reldel)
00824                 reldel = del;
00825         } else {
00826             relocations[i].newPath = NULL;
00827         }
00828     }
00829 
00830     /* stupid bubble sort, but it's probably faster here */
00831     for (i = 0; i < numRelocations; i++) {
00832         int madeSwap;
00833         madeSwap = 0;
00834         for (j = 1; j < numRelocations; j++) {
00835             rpmRelocation tmpReloc;
00836             if (relocations[j - 1].oldPath == NULL || /* XXX can't happen */
00837                 relocations[j    ].oldPath == NULL || /* XXX can't happen */
00838         strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0)
00839                 /*@innercontinue@*/ continue;
00840             /*@-usereleased@*/ /* LCL: ??? */
00841             tmpReloc = relocations[j - 1];
00842             relocations[j - 1] = relocations[j];
00843             relocations[j] = tmpReloc;
00844             /*@=usereleased@*/
00845             madeSwap = 1;
00846         }
00847         if (!madeSwap) break;
00848     }
00849 
00850     if (!_printed) {
00851         _printed = 1;
00852         rpmMessage(RPMMESS_DEBUG, _("========== relocations\n"));
00853         for (i = 0; i < numRelocations; i++) {
00854             if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */
00855             if (relocations[i].newPath == NULL)
00856                 rpmMessage(RPMMESS_DEBUG, _("%5d exclude  %s\n"),
00857                         i, relocations[i].oldPath);
00858             else
00859                 rpmMessage(RPMMESS_DEBUG, _("%5d relocate %s -> %s\n"),
00860                         i, relocations[i].oldPath, relocations[i].newPath);
00861         }
00862     }
00863 
00864     /* Add relocation values to the header */
00865     if (numValid) {
00866         const char ** actualRelocations;
00867         int numActual;
00868 
00869         actualRelocations = xmalloc(numValid * sizeof(*actualRelocations));
00870         numActual = 0;
00871         for (i = 0; i < numValid; i++) {
00872             for (j = 0; j < numRelocations; j++) {
00873                 if (relocations[j].oldPath == NULL || /* XXX can't happen */
00874                     strcmp(validRelocations[i], relocations[j].oldPath))
00875                     /*@innercontinue@*/ continue;
00876                 /* On install, a relocate to NULL means skip the path. */
00877                 if (relocations[j].newPath) {
00878                     actualRelocations[numActual] = relocations[j].newPath;
00879                     numActual++;
00880                 }
00881                 /*@innerbreak@*/ break;
00882             }
00883             if (j == numRelocations) {
00884                 actualRelocations[numActual] = validRelocations[i];
00885                 numActual++;
00886             }
00887         }
00888 
00889         if (numActual)
00890             xx = hae(h, RPMTAG_INSTPREFIXES, RPM_STRING_ARRAY_TYPE,
00891                        (void **) actualRelocations, numActual);
00892 
00893         actualRelocations = _free(actualRelocations);
00894         validRelocations = hfd(validRelocations, validType);
00895     }
00896 
00897     xx = hge(h, RPMTAG_BASENAMES, NULL, (void **) &baseNames, &fileCount);
00898     xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00899     xx = hge(h, RPMTAG_DIRNAMES, NULL, (void **) &dirNames, &dirCount);
00900     xx = hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fFlags, NULL);
00901     xx = hge(h, RPMTAG_FILECOLORS, NULL, (void **) &fColors, NULL);
00902     xx = hge(h, RPMTAG_FILEMODES, NULL, (void **) &fModes, NULL);
00903 
00904     dColors = alloca(dirCount * sizeof(*dColors));
00905     memset(dColors, 0, dirCount * sizeof(*dColors));
00906 
00907     newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount);
00908     memcpy(newDirIndexes, dirIndexes, sizeof(*newDirIndexes) * fileCount);
00909     dirIndexes = newDirIndexes;
00910 
00911     /*
00912      * For all relocations, we go through sorted file/relocation lists 
00913      * backwards so that /usr/local relocations take precedence over /usr 
00914      * ones.
00915      */
00916 
00917     /* Relocate individual paths. */
00918 
00919     for (i = fileCount - 1; i >= 0; i--) {
00920         fileTypes ft;
00921         int fnlen;
00922 
00923         len = reldel +
00924                 strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
00925         /*@-branchstate@*/
00926         if (len >= fileAlloced) {
00927             fileAlloced = len * 2;
00928             fn = xrealloc(fn, fileAlloced);
00929         }
00930         /*@=branchstate@*/
00931 
00932 assert(fn != NULL);             /* XXX can't happen */
00933         *fn = '\0';
00934         fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn;
00935 
00936 if (fColors != NULL) {
00937 /* XXX pkgs may not have unique dirNames, so color all dirNames that match. */
00938 for (j = 0; j < dirCount; j++) {
00939 if (strcmp(dirNames[dirIndexes[i]], dirNames[j])) continue;
00940 dColors[j] |= fColors[i];
00941 }
00942 }
00943 
00944         /*
00945          * See if this file path needs relocating.
00946          */
00947         /*
00948          * XXX FIXME: Would a bsearch of the (already sorted) 
00949          * relocation list be a good idea?
00950          */
00951         for (j = numRelocations - 1; j >= 0; j--) {
00952             if (relocations[j].oldPath == NULL) /* XXX can't happen */
00953                 /*@innercontinue@*/ continue;
00954             len = strcmp(relocations[j].oldPath, "/")
00955                 ? strlen(relocations[j].oldPath)
00956                 : 0;
00957 
00958             if (fnlen < len)
00959                 /*@innercontinue@*/ continue;
00960             /*
00961              * Only subdirectories or complete file paths may be relocated. We
00962              * don't check for '\0' as our directory names all end in '/'.
00963              */
00964             if (!(fn[len] == '/' || fnlen == len))
00965                 /*@innercontinue@*/ continue;
00966 
00967             if (strncmp(relocations[j].oldPath, fn, len))
00968                 /*@innercontinue@*/ continue;
00969             /*@innerbreak@*/ break;
00970         }
00971         if (j < 0) continue;
00972 
00973 /*@-nullderef@*/ /* FIX: fModes may be NULL */
00974         ft = whatis(fModes[i]);
00975 /*@=nullderef@*/
00976 
00977         /* On install, a relocate to NULL means skip the path. */
00978         if (relocations[j].newPath == NULL) {
00979             if (ft == XDIR) {
00980                 /* Start with the parent, looking for directory to exclude. */
00981                 for (j = dirIndexes[i]; j < dirCount; j++) {
00982                     len = strlen(dirNames[j]) - 1;
00983                     while (len > 0 && dirNames[j][len-1] == '/') len--;
00984                     if (fnlen != len)
00985                         /*@innercontinue@*/ continue;
00986                     if (strncmp(fn, dirNames[j], fnlen))
00987                         /*@innercontinue@*/ continue;
00988                     /*@innerbreak@*/ break;
00989                 }
00990             }
00991             if (actions) {
00992                 actions[i] = FA_SKIPNSTATE;
00993                 rpmMessage(RPMMESS_DEBUG, _("excluding %s %s\n"),
00994                         ftstring(ft), fn);
00995             }
00996             continue;
00997         }
00998 
00999         /* Relocation on full paths only, please. */
01000         if (fnlen != len) continue;
01001 
01002         if (actions)
01003             rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"),
01004                     fn, relocations[j].newPath);
01005         nrelocated++;
01006 
01007         strcpy(fn, relocations[j].newPath);
01008         {   char * te = strrchr(fn, '/');
01009             if (te) {
01010                 if (te > fn) te++;      /* root is special */
01011                 fnlen = te - fn;
01012             } else
01013                 te = fn + strlen(fn);
01014             /*@-nullpass -nullderef@*/  /* LCL: te != NULL here. */
01015             if (strcmp(baseNames[i], te)) /* basename changed too? */
01016                 baseNames[i] = alloca_strdup(te);
01017             *te = '\0';                 /* terminate new directory name */
01018             /*@=nullpass =nullderef@*/
01019         }
01020 
01021         /* Does this directory already exist in the directory list? */
01022         for (j = 0; j < dirCount; j++) {
01023             if (fnlen != strlen(dirNames[j]))
01024                 /*@innercontinue@*/ continue;
01025             if (strncmp(fn, dirNames[j], fnlen))
01026                 /*@innercontinue@*/ continue;
01027             /*@innerbreak@*/ break;
01028         }
01029         
01030         if (j < dirCount) {
01031             dirIndexes[i] = j;
01032             continue;
01033         }
01034 
01035         /* Creating new paths is a pita */
01036         if (!haveRelocatedFile) {
01037             const char ** newDirList;
01038 
01039             haveRelocatedFile = 1;
01040             newDirList = xmalloc((dirCount + 1) * sizeof(*newDirList));
01041             for (j = 0; j < dirCount; j++)
01042                 newDirList[j] = alloca_strdup(dirNames[j]);
01043             dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE);
01044             dirNames = newDirList;
01045         } else {
01046             dirNames = xrealloc(dirNames, 
01047                                sizeof(*dirNames) * (dirCount + 1));
01048         }
01049 
01050         dirNames[dirCount] = alloca_strdup(fn);
01051         dirIndexes[i] = dirCount;
01052         dirCount++;
01053     }
01054 
01055     /* Finish off by relocating directories. */
01056     for (i = dirCount - 1; i >= 0; i--) {
01057         for (j = numRelocations - 1; j >= 0; j--) {
01058 
01059            /* XXX Don't autorelocate uncolored directories. */
01060            if (j == p->autorelocatex
01061             && (dColors[i] == 0 || !(dColors[i] & mydColor)))
01062                /*@innercontinue@*/ continue;
01063 
01064             if (relocations[j].oldPath == NULL) /* XXX can't happen */
01065                 /*@innercontinue@*/ continue;
01066             len = strcmp(relocations[j].oldPath, "/")
01067                 ? strlen(relocations[j].oldPath)
01068                 : 0;
01069 
01070             if (len && strncmp(relocations[j].oldPath, dirNames[i], len))
01071                 /*@innercontinue@*/ continue;
01072 
01073             /*
01074              * Only subdirectories or complete file paths may be relocated. We
01075              * don't check for '\0' as our directory names all end in '/'.
01076              */
01077             if (dirNames[i][len] != '/')
01078                 /*@innercontinue@*/ continue;
01079 
01080             if (relocations[j].newPath) { /* Relocate the path */
01081                 const char * s = relocations[j].newPath;
01082                 char * t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1);
01083                 size_t slen;
01084 
01085                 (void) stpcpy( stpcpy(t, s) , dirNames[i] + len);
01086 
01087                 /* Unfortunatly rpmCleanPath strips the trailing slash.. */
01088                 (void) rpmCleanPath(t);
01089                 slen = strlen(t);
01090                 t[slen] = '/';
01091                 t[slen+1] = '\0';
01092 
01093                 if (actions)
01094                     rpmMessage(RPMMESS_DEBUG,
01095                         _("relocating directory %s to %s\n"), dirNames[i], t);
01096                 dirNames[i] = t;
01097                 nrelocated++;
01098             }
01099         }
01100     }
01101 
01102     /* Save original filenames in header and replace (relocated) filenames. */
01103     if (nrelocated) {
01104         int c;
01105         void * d;
01106         rpmTagType t;
01107 
01108         d = NULL;
01109         xx = hge(h, RPMTAG_BASENAMES, &t, &d, &c);
01110         xx = hae(h, RPMTAG_ORIGBASENAMES, t, d, c);
01111         d = hfd(d, t);
01112 
01113         d = NULL;
01114         xx = hge(h, RPMTAG_DIRNAMES, &t, &d, &c);
01115         xx = hae(h, RPMTAG_ORIGDIRNAMES, t, d, c);
01116         d = hfd(d, t);
01117 
01118         d = NULL;
01119         xx = hge(h, RPMTAG_DIRINDEXES, &t, &d, &c);
01120         xx = hae(h, RPMTAG_ORIGDIRINDEXES, t, d, c);
01121         d = hfd(d, t);
01122 
01123         xx = hme(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
01124                           baseNames, fileCount);
01125         fi->bnl = hfd(fi->bnl, RPM_STRING_ARRAY_TYPE);
01126         xx = hge(h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc);
01127 
01128         xx = hme(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
01129                           dirNames, dirCount);
01130         fi->dnl = hfd(fi->dnl, RPM_STRING_ARRAY_TYPE);
01131         xx = hge(h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
01132 
01133         xx = hme(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE,
01134                           dirIndexes, fileCount);
01135         xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
01136     }
01137 
01138     baseNames = hfd(baseNames, RPM_STRING_ARRAY_TYPE);
01139     dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE);
01140 /*@-dependenttrans@*/
01141     fn = _free(fn);
01142 /*@=dependenttrans@*/
01143 
01144     return h;
01145 }
01146 /*@=bounds@*/
01147 
01148 rpmfi rpmfiFree(rpmfi fi)
01149 {
01150     HFD_t hfd = headerFreeData;
01151 
01152     if (fi == NULL) return NULL;
01153 
01154     if (fi->nrefs > 1)
01155         return rpmfiUnlink(fi, fi->Type);
01156 
01157 /*@-modfilesys@*/
01158 if (_rpmfi_debug < 0)
01159 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, fi->Type, fi->fc);
01160 /*@=modfilesys@*/
01161 
01162     /*@-branchstate@*/
01163     if (fi->fc > 0) {
01164         fi->bnl = hfd(fi->bnl, -1);
01165         fi->dnl = hfd(fi->dnl, -1);
01166 
01167         fi->flinks = hfd(fi->flinks, -1);
01168         fi->flangs = hfd(fi->flangs, -1);
01169         fi->fmd5s = hfd(fi->fmd5s, -1);
01170         fi->md5s = _free(fi->md5s);
01171 
01172         fi->cdict = hfd(fi->cdict, -1);
01173 
01174         fi->fuser = hfd(fi->fuser, -1);
01175         fi->fgroup = hfd(fi->fgroup, -1);
01176 
01177         fi->fstates = _free(fi->fstates);
01178 
01179         /*@-evalorder@*/
01180         if (!fi->keep_header && fi->h == NULL) {
01181             fi->fmtimes = _free(fi->fmtimes);
01182             fi->fmodes = _free(fi->fmodes);
01183             fi->fflags = _free(fi->fflags);
01184             fi->vflags = _free(fi->vflags);
01185             fi->fsizes = _free(fi->fsizes);
01186             fi->frdevs = _free(fi->frdevs);
01187             fi->finodes = _free(fi->finodes);
01188             fi->dil = _free(fi->dil);
01189 
01190             fi->fcolors = _free(fi->fcolors);
01191             fi->fcdictx = _free(fi->fcdictx);
01192             fi->ddict = _free(fi->ddict);
01193             fi->fddictx = _free(fi->fddictx);
01194             fi->fddictn = _free(fi->fddictn);
01195 
01196         }
01197         /*@=evalorder@*/
01198     }
01199     /*@=branchstate@*/
01200 
01201     fi->fsm = freeFSM(fi->fsm);
01202 
01203     fi->fn = _free(fi->fn);
01204     fi->apath = _free(fi->apath);
01205     fi->fmapflags = _free(fi->fmapflags);
01206 
01207     fi->obnl = hfd(fi->obnl, -1);
01208     fi->odnl = hfd(fi->odnl, -1);
01209 
01210     fi->fcontexts = hfd(fi->fcontexts, -1);
01211 
01212     fi->actions = _free(fi->actions);
01213     fi->replacedSizes = _free(fi->replacedSizes);
01214     fi->replaced = _free(fi->replaced);
01215 
01216     fi->h = headerFree(fi->h);
01217 
01218     /*@-nullstate -refcounttrans -usereleased@*/
01219     (void) rpmfiUnlink(fi, fi->Type);
01220     memset(fi, 0, sizeof(*fi));         /* XXX trash and burn */
01221     fi = _free(fi);
01222     /*@=nullstate =refcounttrans =usereleased@*/
01223 
01224     return NULL;
01225 }
01226 
01232 static inline unsigned char nibble(char c)
01233         /*@*/
01234 {
01235     if (c >= '0' && c <= '9')
01236         return (c - '0');
01237     if (c >= 'A' && c <= 'F')
01238         return (c - 'A') + 10;
01239     if (c >= 'a' && c <= 'f')
01240         return (c - 'a') + 10;
01241     return 0;
01242 }
01243 
01244 #define _fdupe(_fi, _data)      \
01245     if ((_fi)->_data != NULL)   \
01246         (_fi)->_data = memcpy(xmalloc((_fi)->fc * sizeof(*(_fi)->_data)), \
01247                         (_fi)->_data, (_fi)->fc * sizeof(*(_fi)->_data))
01248 
01249 rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, int scareMem)
01250 {
01251     HGE_t hge =
01252         (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
01253     HFD_t hfd = headerFreeData;
01254     rpmte p;
01255     rpmfi fi = NULL;
01256     const char * Type;
01257     uint_32 * uip;
01258     int dnlmax, bnlmax;
01259     unsigned char * t;
01260     int len;
01261     int xx;
01262     int i;
01263 
01264     if (tagN == RPMTAG_BASENAMES) {
01265         Type = "Files";
01266     } else {
01267         Type = "?Type?";
01268         goto exit;
01269     }
01270 
01271     fi = xcalloc(1, sizeof(*fi));
01272     if (fi == NULL)     /* XXX can't happen */
01273         goto exit;
01274 
01275     fi->magic = RPMFIMAGIC;
01276     fi->Type = Type;
01277     fi->i = -1;
01278     fi->tagN = tagN;
01279 
01280     fi->hge = hge;
01281     fi->hae = (HAE_t) headerAddEntry;
01282     fi->hme = (HME_t) headerModifyEntry;
01283     fi->hre = (HRE_t) headerRemoveEntry;
01284     fi->hfd = headerFreeData;
01285 
01286     fi->h = (scareMem ? headerLink(h) : NULL);
01287 
01288     if (fi->fsm == NULL)
01289         fi->fsm = newFSM();
01290 
01291     /* 0 means unknown */
01292     xx = hge(h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL);
01293     fi->archivePos = 0;
01294     fi->archiveSize = (xx ? *uip : 0);
01295 
01296     if (!hge(h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) {
01297         fi->fc = 0;
01298         fi->dc = 0;
01299         goto exit;
01300     }
01301     xx = hge(h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
01302     xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
01303     xx = hge(h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL);
01304     xx = hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL);
01305     xx = hge(h, RPMTAG_FILEVERIFYFLAGS, NULL, (void **) &fi->vflags, NULL);
01306     xx = hge(h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL);
01307 
01308     xx = hge(h, RPMTAG_FILECOLORS, NULL, (void **) &fi->fcolors, NULL);
01309     fi->color = 0;
01310     if (fi->fcolors != NULL)
01311     for (i = 0; i < fi->fc; i++)
01312         fi->color |= fi->fcolors[i];
01313     xx = hge(h, RPMTAG_CLASSDICT, NULL, (void **) &fi->cdict, &fi->ncdict);
01314     xx = hge(h, RPMTAG_FILECLASS, NULL, (void **) &fi->fcdictx, NULL);
01315 
01316     xx = hge(h, RPMTAG_DEPENDSDICT, NULL, (void **) &fi->ddict, &fi->nddict);
01317     xx = hge(h, RPMTAG_FILEDEPENDSX, NULL, (void **) &fi->fddictx, NULL);
01318     xx = hge(h, RPMTAG_FILEDEPENDSN, NULL, (void **) &fi->fddictn, NULL);
01319 
01320     xx = hge(h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL);
01321     if (xx == 0 || fi->fstates == NULL)
01322         fi->fstates = xcalloc(fi->fc, sizeof(*fi->fstates));
01323     else
01324         _fdupe(fi, fstates);
01325 
01326     fi->action = FA_UNKNOWN;
01327     fi->flags = 0;
01328 
01329 if (fi->actions == NULL)
01330         fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
01331 
01332     fi->keep_header = (scareMem ? 1 : 0);
01333 
01334     /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
01335     fi->mapflags =
01336                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01337 
01338     xx = hge(h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
01339     xx = hge(h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL);
01340 
01341     fi->fmd5s = NULL;
01342     xx = hge(h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
01343 
01344     fi->md5s = NULL;
01345     if (fi->fmd5s) {
01346         t = xmalloc(fi->fc * 16);
01347         fi->md5s = t;
01348         for (i = 0; i < fi->fc; i++) {
01349             const char * fmd5;
01350             int j;
01351 
01352             fmd5 = fi->fmd5s[i];
01353             if (!(fmd5 && *fmd5 != '\0')) {
01354                 memset(t, 0, 16);
01355                 t += 16;
01356                 continue;
01357             }
01358             for (j = 0; j < 16; j++, t++, fmd5 += 2)
01359                 *t = (nibble(fmd5[0]) << 4) | nibble(fmd5[1]);
01360         }
01361         fi->fmd5s = hfd(fi->fmd5s, -1);
01362     }
01363 
01364     /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes, or fcontexts */
01365     xx = hge(h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL);
01366     xx = hge(h, RPMTAG_FILERDEVS, NULL, (void **) &fi->frdevs, NULL);
01367     xx = hge(h, RPMTAG_FILEINODES, NULL, (void **) &fi->finodes, NULL);
01368     xx = hge(h, RPMTAG_FILECONTEXTS, NULL, (void **) &fi->fcontexts, NULL);
01369 
01370     fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
01371 
01372     xx = hge(h, RPMTAG_FILEUSERNAME, NULL, (void **) &fi->fuser, NULL);
01373     xx = hge(h, RPMTAG_FILEGROUPNAME, NULL, (void **) &fi->fgroup, NULL);
01374 
01375     if (ts != NULL)
01376     if (fi != NULL)
01377     if ((p = rpmtsRelocateElement(ts)) != NULL && rpmteType(p) == TR_ADDED
01378      && !headerIsEntry(h, RPMTAG_SOURCEPACKAGE)
01379      && !headerIsEntry(h, RPMTAG_ORIGBASENAMES))
01380     {
01381         const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL);
01382         const char * errstr;
01383         char * newPath;
01384         Header foo;
01385 
01386         /* XXX error handling. */
01387         newPath = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
01388         fmt = _free(fmt);
01389 
01390 #if __ia64__
01391         /* XXX On ia64, change leading /emul/ix86 -> /emul/ia32, ick. */
01392         if (newPath != NULL && *newPath != '\0'
01393          && strlen(newPath) >= (sizeof("/emul/i386")-1)
01394          && newPath[0] == '/' && newPath[1] == 'e' && newPath[2] == 'm'
01395          && newPath[3] == 'u' && newPath[4] == 'l' && newPath[5] == '/'
01396          && newPath[6] == 'i' && newPath[8] == '8' && newPath[9] == '6')
01397         {
01398             newPath[7] = 'a';
01399             newPath[8] = '3';
01400             newPath[9] = '2';
01401         }
01402 #endif
01403  
01404         /* XXX Make sure autoreloc is not already specified. */
01405         i = p->nrelocs;
01406         if (newPath != NULL && *newPath != '\0' && p->relocs != NULL)
01407         for (i = 0; i < p->nrelocs; i++) {
01408 /*@-nullpass@*/ /* XXX {old,new}Path might be NULL */
01409            if (strcmp(p->relocs[i].oldPath, "/"))
01410                 continue;
01411            if (strcmp(p->relocs[i].newPath, newPath))
01412                 continue;
01413 /*@=nullpass@*/
01414            break;
01415         }
01416 
01417         /* XXX test for incompatible arch triggering autorelocation is dumb. */
01418         if (newPath != NULL && *newPath != '\0' && i == p->nrelocs
01419          && p->archScore == 0)
01420         {
01421 
01422             p->relocs =
01423                 xrealloc(p->relocs, (p->nrelocs + 2) * sizeof(*p->relocs));
01424             p->relocs[p->nrelocs].oldPath = xstrdup("/");
01425             p->relocs[p->nrelocs].newPath = xstrdup(newPath);
01426             p->autorelocatex = p->nrelocs;
01427             p->nrelocs++;
01428             p->relocs[p->nrelocs].oldPath = NULL;
01429             p->relocs[p->nrelocs].newPath = NULL;
01430         }
01431         newPath = _free(newPath);
01432 
01433 /* XXX DYING */
01434 if (fi->actions == NULL)
01435         fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
01436         /*@-compdef@*/ /* FIX: fi-md5s undefined */
01437         foo = relocateFileList(ts, fi, h, fi->actions);
01438         /*@=compdef@*/
01439         fi->h = headerFree(fi->h);
01440         fi->h = headerLink(foo);
01441         foo = headerFree(foo);
01442     }
01443 
01444     if (!scareMem) {
01445         _fdupe(fi, fmtimes);
01446         _fdupe(fi, frdevs);
01447         _fdupe(fi, finodes);
01448         _fdupe(fi, fsizes);
01449         _fdupe(fi, fflags);
01450         _fdupe(fi, vflags);
01451         _fdupe(fi, fmodes);
01452         _fdupe(fi, dil);
01453 
01454         _fdupe(fi, fcolors);
01455         _fdupe(fi, fcdictx);
01456 
01457         if (fi->ddict != NULL)
01458             fi->ddict = memcpy(xmalloc(fi->nddict * sizeof(*fi->ddict)),
01459                         fi->ddict, fi->nddict * sizeof(*fi->ddict));
01460 
01461         _fdupe(fi, fddictx);
01462         _fdupe(fi, fddictn);
01463 
01464         fi->h = headerFree(fi->h);
01465     }
01466 
01467     dnlmax = -1;
01468     for (i = 0; i < fi->dc; i++) {
01469         if ((len = strlen(fi->dnl[i])) > dnlmax)
01470             dnlmax = len;
01471     }
01472     bnlmax = -1;
01473     for (i = 0; i < fi->fc; i++) {
01474         if ((len = strlen(fi->bnl[i])) > bnlmax)
01475             bnlmax = len;
01476     }
01477     fi->fnlen = dnlmax + bnlmax + 1;
01478     fi->fn = NULL;
01479 
01480     fi->dperms = 0755;
01481     fi->fperms = 0644;
01482 
01483 exit:
01484 /*@-modfilesys@*/
01485 if (_rpmfi_debug < 0)
01486 fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, Type, (fi ? fi->fc : 0));
01487 /*@=modfilesys@*/
01488 
01489     /*@-compdef -nullstate@*/ /* FIX: rpmfi null annotations */
01490     return rpmfiLink(fi, (fi ? fi->Type : NULL));
01491     /*@=compdef =nullstate@*/
01492 }
01493 
01494 void rpmfiBuildFClasses(Header h,
01495         /*@out@*/ const char *** fclassp, /*@out@*/ int * fcp)
01496 {
01497     int scareMem = 1;
01498     rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
01499     const char * FClass;
01500     const char ** av;
01501     int ac;
01502     size_t nb;
01503     char * t;
01504 
01505     if ((ac = rpmfiFC(fi)) <= 0) {
01506         av = NULL;
01507         ac = 0;
01508         goto exit;
01509     }
01510 
01511     /* Compute size of file class argv array blob. */
01512     nb = (ac + 1) * sizeof(*av);
01513     fi = rpmfiInit(fi, 0);
01514     if (fi != NULL)
01515     while (rpmfiNext(fi) >= 0) {
01516         FClass = rpmfiFClass(fi);
01517         if (FClass && *FClass != '\0')
01518             nb += strlen(FClass);
01519         nb += 1;
01520     }
01521 
01522     /* Create and load file class argv array. */
01523     av = xmalloc(nb);
01524     t = ((char *) av) + ((ac + 1) * sizeof(*av));
01525     ac = 0;
01526     fi = rpmfiInit(fi, 0);
01527     if (fi != NULL)
01528     while (rpmfiNext(fi) >= 0) {
01529         FClass = rpmfiFClass(fi);
01530         av[ac++] = t;
01531         if (FClass && *FClass != '\0')
01532             t = stpcpy(t, FClass);
01533         *t++ = '\0';
01534     }
01535     av[ac] = NULL;      /* XXX tag arrays are not NULL terminated. */
01536     /*@=branchstate@*/
01537 
01538 exit:
01539     fi = rpmfiFree(fi);
01540     /*@-branchstate@*/
01541     if (fclassp)
01542         *fclassp = av;
01543     else
01544         av = _free(av);
01545     /*@=branchstate@*/
01546     if (fcp) *fcp = ac;
01547 }
01548 
01549 void rpmfiBuildFContexts(Header h,
01550         /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
01551 {
01552     int scareMem = 1;
01553     rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
01554     const char * fcontext;
01555     const char ** av;
01556     int ac;
01557     size_t nb;
01558     char * t;
01559 
01560     if ((ac = rpmfiFC(fi)) <= 0) {
01561         av = NULL;
01562         ac = 0;
01563         goto exit;
01564     }
01565 
01566     /* Compute size of argv array blob. */
01567     nb = (ac + 1) * sizeof(*av);
01568     fi = rpmfiInit(fi, 0);
01569     if (fi != NULL)
01570     while (rpmfiNext(fi) >= 0) {
01571         fcontext = rpmfiFContext(fi);
01572         if (fcontext && *fcontext != '\0')
01573             nb += strlen(fcontext);
01574         nb += 1;
01575     }
01576 
01577     /* Create and load argv array. */
01578     av = xmalloc(nb);
01579     t = ((char *) av) + ((ac + 1) * sizeof(*av));
01580     ac = 0;
01581     fi = rpmfiInit(fi, 0);
01582     if (fi != NULL)
01583     while (rpmfiNext(fi) >= 0) {
01584         fcontext = rpmfiFContext(fi);
01585         av[ac++] = t;
01586         if (fcontext && *fcontext != '\0')
01587             t = stpcpy(t, fcontext);
01588         *t++ = '\0';
01589     }
01590     av[ac] = NULL;      /* XXX tag arrays are not NULL terminated. */
01591     /*@=branchstate@*/
01592 
01593 exit:
01594     fi = rpmfiFree(fi);
01595     /*@-branchstate@*/
01596     if (fcontextp)
01597         *fcontextp = av;
01598     else
01599         av = _free(av);
01600     /*@=branchstate@*/
01601     if (fcp) *fcp = ac;
01602 }
01603 
01604 void rpmfiBuildFSContexts(Header h,
01605         /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
01606 {
01607     int scareMem = 1;
01608     rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
01609     const char ** av;
01610     int ac;
01611     size_t nb;
01612     char * t;
01613     char * fctxt = NULL;
01614     size_t fctxtlen = 0;
01615     int * fcnb;
01616 
01617     if ((ac = rpmfiFC(fi)) <= 0) {
01618         av = NULL;
01619         ac = 0;
01620         goto exit;
01621     }
01622 
01623     /* Compute size of argv array blob, concatenating file contexts. */
01624     nb = ac * sizeof(*fcnb);
01625     fcnb = memset(alloca(nb), 0, nb);
01626     ac = 0;
01627     fi = rpmfiInit(fi, 0);
01628     if (fi != NULL)
01629     while (rpmfiNext(fi) >= 0) {
01630         const char * fn = rpmfiFN(fi);
01631         security_context_t scon;
01632 
01633         fcnb[ac] = lgetfilecon(fn, &scon);
01634 /*@-branchstate@*/
01635         if (fcnb[ac] > 0) {
01636             fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
01637             memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
01638             fctxtlen += fcnb[ac];
01639             freecon(scon);
01640         }
01641 /*@=branchstate@*/
01642         ac++;
01643     }
01644 
01645     /* Create and load argv array from concatenated file contexts. */
01646     nb = (ac + 1) * sizeof(*av) + fctxtlen;
01647     av = xmalloc(nb);
01648     t = ((char *) av) + ((ac + 1) * sizeof(*av));
01649     if (fctxt != NULL && fctxtlen > 0)
01650         (void) memcpy(t, fctxt, fctxtlen);
01651     ac = 0;
01652     fi = rpmfiInit(fi, 0);
01653     if (fi != NULL)
01654     while (rpmfiNext(fi) >= 0) {
01655         av[ac] = "";
01656         if (fcnb[ac] > 0) {
01657             av[ac] = t;
01658             t += fcnb[ac];
01659         }
01660         ac++;
01661     }
01662     av[ac] = NULL;      /* XXX tag arrays are not NULL terminated. */
01663 
01664 exit:
01665     fi = rpmfiFree(fi);
01666     /*@-branchstate@*/
01667     if (fcontextp)
01668         *fcontextp = av;
01669     else
01670         av = _free(av);
01671     /*@=branchstate@*/
01672     if (fcp) *fcp = ac;
01673 }
01674 
01675 void rpmfiBuildREContexts(Header h,
01676         /*@out@*/ const char *** fcontextp, /*@out@*/ int * fcp)
01677 {
01678     int scareMem = 1;
01679     rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
01680     rpmsx sx = NULL;
01681     const char ** av = NULL;
01682     int ac;
01683     size_t nb;
01684     char * t;
01685     char * fctxt = NULL;
01686     size_t fctxtlen = 0;
01687     int * fcnb;
01688 
01689     if ((ac = rpmfiFC(fi)) <= 0) {
01690         ac = 0;
01691         goto exit;
01692     }
01693 
01694     /* Read security context patterns. */
01695     sx = rpmsxNew(NULL);
01696 
01697     /* Compute size of argv array blob, concatenating file contexts. */
01698     nb = ac * sizeof(*fcnb);
01699     fcnb = memset(alloca(nb), 0, nb);
01700     ac = 0;
01701     fi = rpmfiInit(fi, 0);
01702     if (fi != NULL)
01703     while (rpmfiNext(fi) >= 0) {
01704         const char * fn = rpmfiFN(fi);
01705         mode_t fmode = rpmfiFMode(fi);
01706         const char * scon;
01707 
01708         scon = rpmsxFContext(sx, fn, fmode);
01709         if (scon != NULL) {
01710             fcnb[ac] = strlen(scon) + 1;
01711 /*@-branchstate@*/
01712             if (fcnb[ac] > 0) {
01713                 fctxt = xrealloc(fctxt, fctxtlen + fcnb[ac]);
01714                 memcpy(fctxt+fctxtlen, scon, fcnb[ac]);
01715                 fctxtlen += fcnb[ac];
01716             }
01717 /*@=branchstate@*/
01718         }
01719         ac++;
01720     }
01721 
01722     /* Create and load argv array from concatenated file contexts. */
01723     nb = (ac + 1) * sizeof(*av) + fctxtlen;
01724     av = xmalloc(nb);
01725     t = ((char *) av) + ((ac + 1) * sizeof(*av));
01726     (void) memcpy(t, fctxt, fctxtlen);
01727     ac = 0;
01728     fi = rpmfiInit(fi, 0);
01729     if (fi != NULL)
01730     while (rpmfiNext(fi) >= 0) {
01731         av[ac] = "";
01732         if (fcnb[ac] > 0) {
01733             av[ac] = t;
01734             t += fcnb[ac];
01735         }
01736         ac++;
01737     }
01738     av[ac] = NULL;      /* XXX tag arrays are not NULL terminated. */
01739 
01740 exit:
01741     fi = rpmfiFree(fi);
01742     sx = rpmsxFree(sx);
01743     /*@-branchstate@*/
01744     if (fcontextp)
01745         *fcontextp = av;
01746     else
01747         av = _free(av);
01748     /*@=branchstate@*/
01749     if (fcp) *fcp = ac;
01750 }
01751 
01752 void rpmfiBuildFDeps(Header h, rpmTag tagN,
01753         /*@out@*/ const char *** fdepsp, /*@out@*/ int * fcp)
01754 {
01755     int scareMem = 1;
01756     rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, scareMem);
01757     rpmds ds = NULL;
01758     const char ** av;
01759     int ac;
01760     size_t nb;
01761     char * t;
01762     char deptype = 'R';
01763     char mydt;
01764     const char * DNEVR;
01765     const int_32 * ddict;
01766     unsigned ix;
01767     int ndx;
01768 
01769     if ((ac = rpmfiFC(fi)) <= 0) {
01770         av = NULL;
01771         ac = 0;
01772         goto exit;
01773     }
01774 
01775     if (tagN == RPMTAG_PROVIDENAME)
01776         deptype = 'P';
01777     else if (tagN == RPMTAG_REQUIRENAME)
01778         deptype = 'R';
01779 
01780     ds = rpmdsNew(h, tagN, scareMem);
01781 
01782     /* Compute size of file depends argv array blob. */
01783     nb = (ac + 1) * sizeof(*av);
01784     fi = rpmfiInit(fi, 0);
01785     if (fi != NULL)
01786     while (rpmfiNext(fi) >= 0) {
01787         ddict = NULL;
01788         ndx = rpmfiFDepends(fi, &ddict);
01789         if (ddict != NULL)
01790         while (ndx-- > 0) {
01791             ix = *ddict++;
01792             mydt = ((ix >> 24) & 0xff);
01793             if (mydt != deptype)
01794                 /*@innercontinue@*/ continue;
01795             ix &= 0x00ffffff;
01796             (void) rpmdsSetIx(ds, ix-1);
01797             if (rpmdsNext(ds) < 0)
01798                 /*@innercontinue@*/ continue;
01799             DNEVR = rpmdsDNEVR(ds);
01800             if (DNEVR != NULL)
01801                 nb += strlen(DNEVR+2) + 1;
01802         }
01803         nb += 1;
01804     }
01805 
01806     /* Create and load file depends argv array. */
01807     av = xmalloc(nb);
01808     t = ((char *) av) + ((ac + 1) * sizeof(*av));
01809     ac = 0;
01810     /*@-branchstate@*/
01811     fi = rpmfiInit(fi, 0);
01812     if (fi != NULL)
01813     while (rpmfiNext(fi) >= 0) {
01814         av[ac++] = t;
01815         ddict = NULL;
01816         ndx = rpmfiFDepends(fi, &ddict);
01817         if (ddict != NULL)
01818         while (ndx-- > 0) {
01819             ix = *ddict++;
01820             mydt = ((ix >> 24) & 0xff);
01821             if (mydt != deptype)
01822                 /*@innercontinue@*/ continue;
01823             ix &= 0x00ffffff;
01824             (void) rpmdsSetIx(ds, ix-1);
01825             if (rpmdsNext(ds) < 0)
01826                 /*@innercontinue@*/ continue;
01827             DNEVR = rpmdsDNEVR(ds);
01828             if (DNEVR != NULL) {
01829                 t = stpcpy(t, DNEVR+2);
01830                 *t++ = ' ';
01831                 *t = '\0';
01832             }
01833         }
01834         *t++ = '\0';
01835     }
01836     /*@=branchstate@*/
01837     av[ac] = NULL;      /* XXX tag arrays are not NULL terminated. */
01838 
01839 exit:
01840     fi = rpmfiFree(fi);
01841     ds = rpmdsFree(ds);
01842     /*@-branchstate@*/
01843     if (fdepsp)
01844         *fdepsp = av;
01845     else
01846         av = _free(av);
01847     /*@=branchstate@*/
01848     if (fcp) *fcp = ac;
01849 }

Generated on Tue Oct 4 09:47:33 2011 for rpm by  doxygen 1.3.9.1