- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# lib/rpmte.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio.h>
    00008 #include <rpmcb.h>              /* XXX fnpyKey */
    00009 #include <rpmlib.h>
    00010
    00011 #include "rpmds.h"
    00012 #include "rpmfi.h"
    00013
    00014 #define _RPMTE_INTERNAL
    00015 #include "rpmte.h"
    00016 #include "rpmts.h"
    00017
    00018 #include "debug.h"
    00019
    00020 /*@unchecked@*/
    00021 int _rpmte_debug = 0;
    00022
    00023 /*@access alKey @*/
    00024 /*@access rpmtsi @*/
    00025
    00026 void rpmteCleanDS(rpmte te)
    00027 {
    00028     te->PRCO = rpmdsFreePRCO(te->PRCO);
    00029 }
    00030
    00035 static void delTE(rpmte p)
    00036         /*@globals fileSystem @*/
    00037         /*@modifies p, fileSystem @*/
    00038 {
    00039     rpmRelocation r;
    00040
    00041     if (p->relocs) {
    00042         for (r = p->relocs; (r->oldPath || r->newPath); r++) {
    00043             r->oldPath = _free(r->oldPath);
    00044             r->newPath = _free(r->newPath);
    00045         }
    00046         p->relocs = _free(p->relocs);
    00047     }
    00048
    00049     rpmteCleanDS(p);
    00050
    00051     p->fi = rpmfiFree(p->fi);
    00052
    00053     if (p->fd != NULL)
    00054         p->fd = fdFree(p->fd, "delTE");
    00055
    00056     p->os = _free(p->os);
    00057     p->arch = _free(p->arch);
    00058     p->epoch = _free(p->epoch);
    00059     p->name = _free(p->name);
    00060     p->NEVR = _free(p->NEVR);
    00061     p->NEVRA = _free(p->NEVRA);
    00062     p->pkgid = _free(p->pkgid);
    00063     p->hdrid = _free(p->hdrid);
    00064
    00065     p->replaced = _free(p->replaced);
    00066
    00067     p->flink.NEVRA = argvFree(p->flink.NEVRA);
    00068     p->flink.Pkgid = argvFree(p->flink.Pkgid);
    00069     p->flink.Hdrid = argvFree(p->flink.Hdrid);
    00070     p->blink.NEVRA = argvFree(p->blink.NEVRA);
    00071     p->blink.Pkgid = argvFree(p->blink.Pkgid);
    00072     p->blink.Hdrid = argvFree(p->blink.Hdrid);
    00073
    00074     p->h = headerFree(p->h);
    00075
    00076     memset(p, 0, sizeof(*p));   /* XXX trash and burn */
    00077     /*@-nullstate@*/ /* FIX: p->{NEVR,name} annotations */
    00078     return;
    00079     /*@=nullstate@*/
    00080 }
    00081
    00090 static void addTE(rpmts ts, rpmte p, Header h,
    00091                 /*@dependent@*/ /*@null@*/ fnpyKey key,
    00092                 /*@null@*/ rpmRelocation relocs)
    00093         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00094         /*@modifies ts, p, h,
    00095                 rpmGlobalMacroContext, fileSystem, internalState @*/
    00096 {
    00097     int scareMem = 0;
    00098     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00099     int xx;
    00100
    00101     he->tag = RPMTAG_NVRA;
    00102     xx = headerGet(h, he, 0);
    00103 assert(he->p.str != NULL);
    00104     p->NEVR = (xx ? he->p.str : xstrdup("?N-?V-?R.?A"));
    00105     p->name = xstrdup(p->NEVR);
    00106     if ((p->release = strrchr(p->name, '-')) != NULL)
    00107         *p->release++ = '\0';
    00108     if ((p->version = strrchr(p->name, '-')) != NULL)
    00109         *p->version++ = '\0';
    00110
    00111     p->db_instance = 0;
    00112
    00113     he->tag = RPMTAG_HDRID;
    00114     xx = headerGet(h, he, 0);
    00115     p->hdrid = (xx ? he->p.str : xstrdup("?RPMTAG_HDRID?"));
    00116
    00117     he->tag = RPMTAG_PKGID;
    00118     xx = headerGet(h, he, 0);
    00119     if (he->p.ui8p != NULL) {
    00120         static const char hex[] = "0123456789abcdef";
    00121         char * t;
    00122         int i;
    00123
    00124         p->pkgid = t = xmalloc((2*he->c) + 1);
    00125         for (i = 0 ; i < he->c; i++) {
    00126             *t++ = hex[ (unsigned)((he->p.ui8p[i] >> 4) & 0x0f) ];
    00127             *t++ = hex[ (unsigned)((he->p.ui8p[i]     ) & 0x0f) ];
    00128         }
    00129         *t = '\0';
    00130         he->p.ptr = _free(he->p.ptr);
    00131     } else
    00132         p->pkgid = NULL;
    00133
    00134     he->tag = RPMTAG_ARCH;
    00135     xx = headerGet(h, he, 0);
    00136     p->arch = (xx ? he->p.str : xstrdup("?RPMTAG_ARCH?"));
    00137
    00138     he->tag = RPMTAG_OS;
    00139     xx = headerGet(h, he, 0);
    00140     p->os = (xx ? he->p.str : xstrdup("?RPMTAG_OS?"));
    00141
    00142     p->isSource =
    00143         (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
    00144          headerIsEntry(h, RPMTAG_ARCH) != 0);
    00145
    00146     p->NEVRA = xstrdup(p->NEVR);
    00147
    00148     he->tag = RPMTAG_EPOCH;
    00149     xx = headerGet(h, he, 0);
    00150     if (he->p.ui32p != NULL) {
    00151         p->epoch = xmalloc(20);
    00152         sprintf(p->epoch, "%u", he->p.ui32p[0]);
    00153         he->p.ptr = _free(he->p.ptr);
    00154     } else
    00155         p->epoch = NULL;
    00156
    00157     p->installed = 0;
    00158
    00159     p->nrelocs = 0;
    00160     p->relocs = NULL;
    00161     if (relocs != NULL) {
    00162         rpmRelocation r;
    00163         int i;
    00164
    00165         for (r = relocs; r->oldPath || r->newPath; r++)
    00166             p->nrelocs++;
    00167         p->relocs = xmalloc((p->nrelocs + 1) * sizeof(*p->relocs));
    00168
    00169         for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
    00170             p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
    00171             p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
    00172         }
    00173         p->relocs[i].oldPath = NULL;
    00174         p->relocs[i].newPath = NULL;
    00175     }
    00176     p->autorelocatex = -1;
    00177
    00178     p->key = key;
    00179     p->fd = NULL;
    00180
    00181     p->replaced = NULL;
    00182
    00183     p->pkgFileSize = 0;
    00184
    00185     p->PRCO = rpmdsNewPRCO(h);
    00186
    00187     {   rpmte savep = rpmtsSetRelocateElement(ts, p);
    00188         p->fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
    00189         (void) rpmtsSetRelocateElement(ts, savep);
    00190     }
    00191
    00192     rpmteColorDS(p, RPMTAG_PROVIDENAME);
    00193     rpmteColorDS(p, RPMTAG_REQUIRENAME);
    00194 /*@-compdef@*/
    00195     return;
    00196 /*@=compdef@*/
    00197 }
    00198
    00199 rpmte rpmteFree(rpmte te)
    00200 {
    00201     if (te != NULL) {
    00202         delTE(te);
    00203         memset(te, 0, sizeof(*te));     /* XXX trash and burn */
    00204         te = _free(te);
    00205     }
    00206     return NULL;
    00207 }
    00208
    00209 rpmte rpmteNew(const rpmts ts, Header h,
    00210                 rpmElementType type,
    00211                 fnpyKey key,
    00212                 rpmRelocation relocs,
    00213                 int dboffset,
    00214                 alKey pkgKey)
    00215 {
    00216     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00217     rpmte p = xcalloc(1, sizeof(*p));
    00218     int xx;
    00219
    00220     p->type = type;
    00221
    00222     addTE(ts, p, h, key, relocs);
    00223     switch (type) {
    00224     case TR_ADDED:
    00225         p->u.addedKey = pkgKey;
    00226         /* XXX 256 is only an estimate of signature header. */
    00227         p->pkgFileSize = 96 + 256;
    00228         he->tag = RPMTAG_SIGSIZE;
    00229         xx = headerGet(h, he, 0);
    00230         if (xx && he->p.ui32p)
    00231             p->pkgFileSize += *he->p.ui32p;
    00232         he->p.ptr = _free(he->p.ptr);
    00233         break;
    00234     case TR_REMOVED:
    00235         p->u.addedKey = pkgKey;
    00236         p->u.removed.dboffset = dboffset;
    00237         break;
    00238     }
    00239     return p;
    00240 }
    00241
    00242 /* Get the DB Instance value */
    00243 unsigned int rpmteDBInstance(rpmte te)
    00244 {
    00245     return (te != NULL ? te->db_instance : 0);
    00246 }
    00247
    00248 /* Set the DB Instance value */
    00249 void rpmteSetDBInstance(rpmte te, unsigned int instance)
    00250 {
    00251     if (te != NULL)
    00252         te->db_instance = instance;
    00253 }
    00254
    00255 Header rpmteHeader(rpmte te)
    00256 {
    00257     return (te != NULL && te->h != NULL ? headerLink(te->h) : NULL);
    00258 }
    00259
    00260 Header rpmteSetHeader(rpmte te, Header h)
    00261 {
    00262     if (te != NULL)  {
    00263         te->h = headerFree(te->h);
    00264         if (h != NULL)
    00265             te->h = headerLink(h);
    00266     }
    00267     return NULL;
    00268 }
    00269
    00270 rpmElementType rpmteType(rpmte te)
    00271 {
    00272     return (te != NULL ? te->type : -1);
    00273 }
    00274
    00275 const char * rpmteN(rpmte te)
    00276 {
    00277     return (te != NULL ? te->name : NULL);
    00278 }
    00279
    00280 const char * rpmteE(rpmte te)
    00281 {
    00282     return (te != NULL ? te->epoch : NULL);
    00283 }
    00284
    00285 const char * rpmteV(rpmte te)
    00286 {
    00287     return (te != NULL ? te->version : NULL);
    00288 }
    00289
    00290 const char * rpmteR(rpmte te)
    00291 {
    00292     return (te != NULL ? te->release : NULL);
    00293 }
    00294
    00295 const char * rpmteA(rpmte te)
    00296 {
    00297     return (te != NULL ? te->arch : NULL);
    00298 }
    00299
    00300 const char * rpmteO(rpmte te)
    00301 {
    00302     return (te != NULL ? te->os : NULL);
    00303 }
    00304
    00305 int rpmteIsSource(rpmte te)
    00306 {
    00307     return (te != NULL ? te->isSource : 0);
    00308 }
    00309
    00310 uint32_t rpmteColor(rpmte te)
    00311 {
    00312     return (te != NULL ? te->color : 0);
    00313 }
    00314
    00315 uint32_t rpmteSetColor(rpmte te, uint32_t color)
    00316 {
    00317     int ocolor = 0;
    00318     if (te != NULL) {
    00319         ocolor = te->color;
    00320         te->color = color;
    00321     }
    00322     return ocolor;
    00323 }
    00324
    00325 uint32_t rpmtePkgFileSize(rpmte te)
    00326 {
    00327     return (te != NULL ? te->pkgFileSize : 0);
    00328 }
    00329
    00330 int rpmteDepth(rpmte te)
    00331 {
    00332     return (te != NULL ? te->depth : 0);
    00333 }
    00334
    00335 int rpmteSetDepth(rpmte te, int ndepth)
    00336 {
    00337     int odepth = 0;
    00338     if (te != NULL) {
    00339         odepth = te->depth;
    00340         te->depth = ndepth;
    00341     }
    00342     return odepth;
    00343 }
    00344
    00345 int rpmteBreadth(rpmte te)
    00346 {
    00347     return (te != NULL ? te->depth : 0);
    00348 }
    00349
    00350 int rpmteSetBreadth(rpmte te, int nbreadth)
    00351 {
    00352     int obreadth = 0;
    00353     if (te != NULL) {
    00354         obreadth = te->breadth;
    00355         te->breadth = nbreadth;
    00356     }
    00357     return obreadth;
    00358 }
    00359
    00360 int rpmteNpreds(rpmte te)
    00361 {
    00362     return (te != NULL ? te->npreds : 0);
    00363 }
    00364
    00365 int rpmteSetNpreds(rpmte te, int npreds)
    00366 {
    00367     int opreds = 0;
    00368     if (te != NULL) {
    00369         opreds = te->npreds;
    00370         te->npreds = npreds;
    00371     }
    00372     return opreds;
    00373 }
    00374
    00375 int rpmteTree(rpmte te)
    00376 {
    00377     return (te != NULL ? te->tree : 0);
    00378 }
    00379
    00380 int rpmteSetTree(rpmte te, int ntree)
    00381 {
    00382     int otree = 0;
    00383     if (te != NULL) {
    00384         otree = te->tree;
    00385         te->tree = ntree;
    00386     }
    00387     return otree;
    00388 }
    00389
    00390 rpmte rpmteParent(rpmte te)
    00391 {
    00392     return (te != NULL ? te->parent : NULL);
    00393 }
    00394
    00395 rpmte rpmteSetParent(rpmte te, rpmte pte)
    00396 {
    00397     rpmte opte = NULL;
    00398     if (te != NULL) {
    00399         opte = te->parent;
    00400         /*@-assignexpose -temptrans@*/
    00401         te->parent = pte;
    00402         /*@=assignexpose =temptrans@*/
    00403     }
    00404     return opte;
    00405 }
    00406
    00407 int rpmteDegree(rpmte te)
    00408 {
    00409     return (te != NULL ? te->degree : 0);
    00410 }
    00411
    00412 int rpmteSetDegree(rpmte te, int ndegree)
    00413 {
    00414     int odegree = 0;
    00415     if (te != NULL) {
    00416         odegree = te->degree;
    00417         te->degree = ndegree;
    00418     }
    00419     return odegree;
    00420 }
    00421
    00422 tsortInfo rpmteTSI(rpmte te)
    00423 {
    00424     /*@-compdef -retalias -retexpose -usereleased @*/
    00425     return te->tsi;
    00426     /*@=compdef =retalias =retexpose =usereleased @*/
    00427 }
    00428
    00429 void rpmteFreeTSI(rpmte te)
    00430 {
    00431     if (te != NULL && rpmteTSI(te) != NULL) {
    00432         tsortInfo tsi;
    00433
    00434         /* Clean up tsort remnants (if any). */
    00435         while ((tsi = rpmteTSI(te)->tsi_next) != NULL) {
    00436             rpmteTSI(te)->tsi_next = tsi->tsi_next;
    00437             tsi->tsi_next = NULL;
    00438             tsi = _free(tsi);
    00439         }
    00440         te->tsi = _free(te->tsi);
    00441     }
    00442     /*@-nullstate@*/ /* FIX: te->tsi is NULL */
    00443     return;
    00444     /*@=nullstate@*/
    00445 }
    00446
    00447 void rpmteNewTSI(rpmte te)
    00448 {
    00449     if (te != NULL) {
    00450         rpmteFreeTSI(te);
    00451         te->tsi = xcalloc(1, sizeof(*te->tsi));
    00452     }
    00453 }
    00454
    00455 alKey rpmteAddedKey(rpmte te)
    00456 {
    00457     return (te != NULL ? te->u.addedKey : RPMAL_NOMATCH);
    00458 }
    00459
    00460 alKey rpmteSetAddedKey(rpmte te, alKey npkgKey)
    00461 {
    00462     alKey opkgKey = RPMAL_NOMATCH;
    00463     if (te != NULL) {
    00464         opkgKey = te->u.addedKey;
    00465         te->u.addedKey = npkgKey;
    00466     }
    00467     return opkgKey;
    00468 }
    00469
    00470
    00471 int rpmteDBOffset(rpmte te)
    00472 {
    00473     return (te != NULL ? te->u.removed.dboffset : 0);
    00474 }
    00475
    00476 const char * rpmteNEVR(rpmte te)
    00477 {
    00478     return (te != NULL ? te->NEVR : NULL);
    00479 }
    00480
    00481 const char * rpmteNEVRA(rpmte te)
    00482 {
    00483     return (te != NULL ? te->NEVRA : NULL);
    00484 }
    00485
    00486 const char * rpmtePkgid(rpmte te)
    00487 {
    00488     return (te != NULL ? te->pkgid : NULL);
    00489 }
    00490
    00491 const char * rpmteHdrid(rpmte te)
    00492 {
    00493     return (te != NULL ? te->hdrid : NULL);
    00494 }
    00495
    00496 FD_t rpmteFd(rpmte te)
    00497 {
    00498     /*@-compdef -refcounttrans -retalias -retexpose -usereleased @*/
    00499     return (te != NULL ? te->fd : NULL);
    00500     /*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
    00501 }
    00502
    00503 fnpyKey rpmteKey(rpmte te)
    00504 {
    00505     return (te != NULL ? te->key : NULL);
    00506 }
    00507
    00508 rpmds rpmteDS(rpmte te, rpmTag tag)
    00509 {
    00510     return (te != NULL ? rpmdsFromPRCO(te->PRCO, tag) : NULL);
    00511 }
    00512
    00513 rpmfi rpmteFI(rpmte te, rpmTag tag)
    00514 {
    00515     /*@-compdef -refcounttrans -retalias -retexpose -usereleased @*/
    00516     if (te == NULL)
    00517         return NULL;
    00518
    00519     if (tag == RPMTAG_BASENAMES)
    00520         return te->fi;
    00521     else
    00522         return NULL;
    00523     /*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
    00524 }
    00525
    00526 void rpmteColorDS(rpmte te, rpmTag tag)
    00527 {
    00528     rpmfi fi = rpmteFI(te, RPMTAG_BASENAMES);
    00529     rpmds ds = rpmteDS(te, tag);
    00530     char deptype = 'R';
    00531     char mydt;
    00532     const uint32_t * ddict;
    00533     uint32_t * colors;
    00534     uint32_t * refs;
    00535     uint32_t val;
    00536     int Count;
    00537     size_t nb;
    00538     unsigned ix;
    00539     int ndx, i;
    00540
    00541     if (!(te && (Count = rpmdsCount(ds)) > 0 && rpmfiFC(fi) > 0))
    00542         return;
    00543
    00544     switch (tag) {
    00545     default:
    00546         return;
    00547         /*@notreached@*/ break;
    00548     case RPMTAG_PROVIDENAME:
    00549         deptype = 'P';
    00550         break;
    00551     case RPMTAG_REQUIRENAME:
    00552         deptype = 'R';
    00553         break;
    00554     }
    00555
    00556     nb = Count * sizeof(*colors);
    00557     colors = memset(alloca(nb), 0, nb);
    00558     nb = Count * sizeof(*refs);
    00559     refs = memset(alloca(nb), -1, nb);
    00560
    00561     /* Calculate dependency color and reference count. */
    00562     fi = rpmfiInit(fi, 0);
    00563     if (fi != NULL)
    00564     while (rpmfiNext(fi) >= 0) {
    00565         val = rpmfiFColor(fi);
    00566         ddict = NULL;
    00567         ndx = rpmfiFDepends(fi, &ddict);
    00568         if (ddict != NULL)
    00569         while (ndx-- > 0) {
    00570             ix = *ddict++;
    00571             mydt = ((ix >> 24) & 0xff);
    00572             if (mydt != deptype)
    00573                 /*@innercontinue@*/ continue;
    00574             ix &= 0x00ffffff;
    00575 assert (ix < Count);
    00576             colors[ix] |= val;
    00577             refs[ix]++;
    00578         }
    00579     }
    00580
    00581     /* Set color/refs values in dependency set. */
    00582     ds = rpmdsInit(ds);
    00583     while ((i = rpmdsNext(ds)) >= 0) {
    00584         val = colors[i];
    00585         te->color |= val;
    00586         (void) rpmdsSetColor(ds, val);
    00587         val = refs[i];
    00588         (void) rpmdsSetRefs(ds, val);
    00589     }
    00590 }
    00591
    00592 /*@unchecked@*/
    00593 static int __mydebug = 0;
    00594
    00595 int rpmteChain(rpmte p, rpmte q, Header oh, const char * msg)
    00596 {
    00597     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00598     const char * blinkNEVRA = NULL;
    00599     const char * blinkPkgid = NULL;
    00600     const char * blinkHdrid = NULL;
    00601     int xx;
    00602
    00603     if (msg == NULL)
    00604         msg = "";
    00605     he->tag = RPMTAG_NVRA;
    00606     xx = headerGet(oh, he, 0);
    00607 assert(he->p.str != NULL);
    00608     blinkNEVRA = he->p.str;
    00609
    00610     /*
    00611      * Convert binary pkgid to a string.
    00612      * XXX Yum's borken conception of a "header" doesn't have signature
    00613      * tags appended.
    00614      */
    00615     he->tag = RPMTAG_PKGID;
    00616     xx = headerGet(oh, he, 0);
    00617     if (xx && he->p.ui8p != NULL) {
    00618         static const char hex[] = "0123456789abcdef";
    00619         char * t;
    00620         int i;
    00621
    00622         blinkPkgid = t = xmalloc((2*he->c) + 1);
    00623         for (i = 0 ; i < he->c; i++) {
    00624             *t++ = hex[ ((he->p.ui8p[i] >> 4) & 0x0f) ];
    00625             *t++ = hex[ ((he->p.ui8p[i]     ) & 0x0f) ];
    00626         }
    00627         *t = '\0';
    00628         he->p.ptr = _free(he->p.ptr);
    00629     } else
    00630         blinkPkgid = NULL;
    00631
    00632     he->tag = RPMTAG_HDRID;
    00633     xx = headerGet(oh, he, 0);
    00634     blinkHdrid = he->p.str;
    00635
    00636 /*@-modfilesys@*/
    00637 if (__mydebug)
    00638 fprintf(stderr, "%s argvAdd(&q->flink.NEVRA, \"%s\")\n", msg, p->NEVRA);
    00639         xx = argvAdd(&q->flink.NEVRA, p->NEVRA);
    00640 if (__mydebug)
    00641 fprintf(stderr, "%s argvAdd(&p->blink.NEVRA, \"%s\")\n", msg, blinkNEVRA);
    00642         xx = argvAdd(&p->blink.NEVRA, blinkNEVRA);
    00643 if (__mydebug)
    00644 fprintf(stderr, "%s argvAdd(&q->flink.Pkgid, \"%s\")\n", msg, p->pkgid);
    00645     if (p->pkgid != NULL)
    00646         xx = argvAdd(&q->flink.Pkgid, p->pkgid);
    00647 if (__mydebug)
    00648 fprintf(stderr, "%s argvAdd(&p->blink.Pkgid, \"%s\")\n", msg, blinkPkgid);
    00649     if (blinkPkgid != NULL)
    00650         xx = argvAdd(&p->blink.Pkgid, blinkPkgid);
    00651 if (__mydebug)
    00652 fprintf(stderr, "%s argvAdd(&q->flink.Hdrid, \"%s\")\n", msg, p->hdrid);
    00653     if (p->hdrid != NULL)
    00654         xx = argvAdd(&q->flink.Hdrid, p->hdrid);
    00655 if (__mydebug)
    00656 fprintf(stderr, "%s argvAdd(&p->blink.Hdrid, \"%s\")\n", msg, blinkHdrid);
    00657     if (blinkHdrid != NULL)
    00658         xx = argvAdd(&p->blink.Hdrid, blinkHdrid);
    00659 /*@=modfilesys@*/
    00660
    00661     blinkNEVRA = _free(blinkNEVRA);
    00662     blinkPkgid = _free(blinkPkgid);
    00663     blinkHdrid = _free(blinkHdrid);
    00664
    00665     return 0;
    00666 }
    00667
    00668 int rpmtsiOc(rpmtsi tsi)
    00669 {
    00670     return tsi->ocsave;
    00671 }
    00672
    00673 rpmtsi XrpmtsiFree(/*@only@*//*@null@*/ rpmtsi tsi,
    00674                 const char * fn, unsigned int ln)
    00675 {
    00676     /* XXX watchout: a funky recursion segfaults here iff nrefs is wrong. */
    00677 /*@-internalglobs@*/
    00678     if (tsi)
    00679         tsi->ts = rpmtsFree(tsi->ts);
    00680 /*@=internalglobs@*/
    00681
    00682 /*@-modfilesys@*/
    00683 if (_rpmte_debug)
    00684 fprintf(stderr, "*** tsi %p -- %s:%d\n", tsi, fn, ln);
    00685 /*@=modfilesys@*/
    00686     return _free(tsi);
    00687 }
    00688
    00689 rpmtsi XrpmtsiInit(rpmts ts, const char * fn, unsigned int ln)
    00690 {
    00691     rpmtsi tsi = NULL;
    00692
    00693     tsi = xcalloc(1, sizeof(*tsi));
    00694     tsi->ts = rpmtsLink(ts, "rpmtsi");
    00695     tsi->reverse = 0;
    00696     tsi->oc = (tsi->reverse ? (rpmtsNElements(ts) - 1) : 0);
    00697     tsi->ocsave = tsi->oc;
    00698 /*@-modfilesys@*/
    00699 if (_rpmte_debug)
    00700 fprintf(stderr, "*** tsi %p ++ %s:%d\n", tsi, fn, ln);
    00701 /*@=modfilesys@*/
    00702     return tsi;
    00703 }
    00704
    00710 static /*@null@*/ /*@dependent@*/
    00711 rpmte rpmtsiNextElement(rpmtsi tsi)
    00712         /*@modifies tsi @*/
    00713 {
    00714     rpmte te = NULL;
    00715     int oc = -1;
    00716
    00717     if (tsi == NULL || tsi->ts == NULL || rpmtsNElements(tsi->ts) <= 0)
    00718         return te;
    00719
    00720     if (tsi->reverse) {
    00721         if (tsi->oc >= 0)               oc = tsi->oc--;
    00722     } else {
    00723         if (tsi->oc < rpmtsNElements(tsi->ts))  oc = tsi->oc++;
    00724     }
    00725     tsi->ocsave = oc;
    00726     if (oc != -1)
    00727         te = rpmtsElement(tsi->ts, oc);
    00728     return te;
    00729 }
    00730
    00731 rpmte rpmtsiNext(rpmtsi tsi, rpmElementType type)
    00732 {
    00733     rpmte te;
    00734
    00735     while ((te = rpmtsiNextElement(tsi)) != NULL) {
    00736         if (type == 0 || (te->type & type) != 0)
    00737             break;
    00738     }
    00739     return te;
    00740 }