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

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2