3 * Routine(s) to handle a "rpmts" transaction sets.
7 #include "rpmio_internal.h" /* XXX for pgp and beecrypt */
9 #include <rpmmacro.h> /* XXX rpmtsOpenDB() needs rpmGetPath */
11 #include "rpmdb.h" /* XXX stealing db->db_mode. */
17 #define _RPMTE_INTERNAL /* XXX te->h */
20 #define _RPMTS_INTERNAL
23 /* XXX FIXME: merge with existing (broken?) tests in system.h */
24 /* portability fiddles */
25 #if STATFS_IN_SYS_STATVFS
27 #if defined(__LCLINT__)
28 /*@-declundef -exportheader -protoparammatch @*/ /* LCL: missing annotation */
29 extern int statvfs (const char * file, /*@out@*/ struct statvfs * buf)
30 /*@globals fileSystem @*/
31 /*@modifies *buf, fileSystem @*/;
32 /*@=declundef =exportheader =protoparammatch @*/
35 # include <sys/statvfs.h>
38 # if STATFS_IN_SYS_VFS
41 # if STATFS_IN_SYS_MOUNT
42 # include <sys/mount.h>
44 # if STATFS_IN_SYS_STATFS
45 # include <sys/statfs.h>
53 /*@access rpmdb @*/ /* XXX db->db_chrootDone, NULL */
56 /*@access rpmDiskSpaceInfo @*/
61 /*@access pgpDigParams @*/
66 char * hGetNEVR(Header h, const char ** np)
68 const char * n, * v, * r;
71 (void) headerNVR(h, &n, &v, &r);
72 NVR = t = xcalloc(1, strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
85 uint_32 hGetColor(Header h)
87 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
95 if (hge(h, RPMTAG_FILECOLORS, NULL, (void **)&fcolors, &ncolors)
96 && fcolors != NULL && ncolors > 0)
99 for (i = 0; i < ncolors; i++)
100 hcolor |= fcolors[i];
108 rpmts XrpmtsUnlink(rpmts ts, const char * msg, const char * fn, unsigned ln)
112 fprintf(stderr, "--> ts %p -- %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
118 rpmts XrpmtsLink(rpmts ts, const char * msg, const char * fn, unsigned ln)
123 fprintf(stderr, "--> ts %p ++ %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
125 /*@-refcounttrans@*/ return ts; /*@=refcounttrans@*/
128 int rpmtsCloseDB(rpmts ts)
132 if (ts->rdb != NULL) {
133 rc = rpmdbClose(ts->rdb);
139 int rpmtsOpenDB(rpmts ts, int dbmode)
143 if (ts->rdb != NULL && ts->dbmode == dbmode)
146 (void) rpmtsCloseDB(ts);
148 /* XXX there's a potential db lock race here. */
151 rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
154 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
155 rpmMessage(RPMMESS_ERROR,
156 _("cannot open Packages database in %s\n"), dn);
162 int rpmtsInitDB(rpmts ts, int dbmode)
164 return rpmdbInit(ts->rootDir, dbmode);
167 int rpmtsRebuildDB(rpmts ts)
170 if (!(ts->vsflags & RPMVSF_NOHDRCHK))
171 rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
173 rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
177 int rpmtsVerifyDB(rpmts ts)
179 return rpmdbVerify(ts->rootDir);
182 rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
183 const void * keyp, size_t keylen)
185 rpmdbMatchIterator mi;
186 if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
188 mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
189 if (mi && !(ts->vsflags & RPMVSF_NOHDRCHK))
190 (void) rpmdbSetHdrChk(mi, ts, headerCheck);
194 rpmRC rpmtsFindPubkey(rpmts ts)
196 const void * sig = rpmtsSig(ts);
197 pgpDig dig = rpmtsDig(ts);
198 pgpDigParams sigp = rpmtsSignature(ts);
199 pgpDigParams pubp = rpmtsSignature(ts);
203 if (sig == NULL || dig == NULL || sigp == NULL || pubp == NULL) {
208 if (ts->pkpkt == NULL
209 || memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid)))
212 rpmdbMatchIterator mi;
215 ts->pkpkt = _free(ts->pkpkt);
217 memset(ts->pksignid, 0, sizeof(ts->pksignid));
219 /* Retrieve the pubkey that matches the signature. */
220 mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
221 while ((h = rpmdbNextIterator(mi)) != NULL) {
222 const char ** pubkeys;
225 if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc))
227 ix = rpmdbGetIteratorFileNum(mi);
230 || b64decode(pubkeys[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
233 pubkeys = headerFreeData(pubkeys, pt);
236 mi = rpmdbFreeIterator(mi);
238 /* Was a matching pubkey found? */
239 if (ix < 0 || ts->pkpkt == NULL) {
245 * Can the pubkey packets be parsed?
246 * Do the parameters match the signature?
248 if (pgpPrtPkts(ts->pkpkt, ts->pkpktlen, NULL, 0)
249 && sigp->pubkey_algo == pubp->pubkey_algo
251 && sigp->hash_algo == pubp->hash_algo
253 && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)))
255 ts->pkpkt = _free(ts->pkpkt);
261 /* XXX Verify the pubkey signature. */
263 /* Packet looks good, save the signer id. */
265 memcpy(ts->pksignid, sigp->signid, sizeof(ts->pksignid));
268 rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n",
269 (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" :
270 (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")),
271 pgpHexStr(sigp->signid, sizeof(sigp->signid)));
277 if (ts->pkpkt == NULL) {
278 const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
279 if (pgpReadPkts(pkfn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY) {
289 /* Retrieve parameters from pubkey packet(s). */
290 xx = pgpPrtPkts(ts->pkpkt, ts->pkpktlen, dig, 0);
292 /* Do the parameters match the signature? */
293 if (sigp->pubkey_algo == pubp->pubkey_algo
295 && sigp->hash_algo == pubp->hash_algo
297 && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) )
302 /* XXX Verify the signature signature. */
308 int rpmtsCloseSDB(rpmts ts)
312 if (ts->sdb != NULL) {
313 rc = rpmdbClose(ts->sdb);
319 int rpmtsOpenSDB(rpmts ts, int dbmode)
321 static int has_sdbpath = -1;
324 if (ts->sdb != NULL && ts->sdbmode == dbmode)
328 has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}");
330 /* If not configured, don't try to open. */
331 if (has_sdbpath <= 0)
334 addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT);
336 rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644);
339 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
340 rpmMessage(RPMMESS_WARNING,
341 _("cannot open Solve database in %s\n"), dn);
344 delMacro(NULL, "_dbpath");
350 * Compare suggested package resolutions (qsort/bsearch).
351 * @param a 1st instance address
352 * @param b 2nd instance address
353 * @return result of comparison
355 static int sugcmp(const void * a, const void * b)
359 const char * astr = *(const char **)a;
360 const char * bstr = *(const char **)b;
362 return strcmp(astr, bstr);
366 int rpmtsSolve(rpmts ts, rpmds ds, /*@unused@*/ const void * data)
371 rpmdbMatchIterator mi;
379 int rc = 1; /* assume not found */
382 /* Make suggestions only for install Requires: */
383 if (ts->goal != TSM_INSTALL)
386 if (rpmdsTagN(ds) != RPMTAG_REQUIRENAME)
393 if (ts->sdb == NULL) {
394 xx = rpmtsOpenSDB(ts, ts->sdbmode);
398 /* Look for a matching Provides: in suggested universe. */
399 rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME);
401 mi = rpmdbInitIterator(ts->sdb, rpmtag, keyp, keylen);
405 while ((h = rpmdbNextIterator(mi)) != NULL) {
411 if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1))
414 /* XXX Prefer the shortest name if given alternatives. */
417 if (headerGetEntry(h, RPMTAG_NAME, NULL, (void **)&hname, NULL)) {
419 hnamelen = strlen(hname);
421 if (bhnamelen > 0 && hnamelen > bhnamelen)
424 /* XXX Prefer the newest build if given alternatives. */
426 if (headerGetEntry(h, RPMTAG_BUILDTIME, NULL, (void **)&ip, NULL))
435 bhnamelen = hnamelen;
437 mi = rpmdbFreeIterator(mi);
439 /* Is there a suggested resolution? */
443 /* Format the suggestion. */
444 qfmt = rpmExpand("%{?_solve_name_fmt}", NULL);
445 if (qfmt == NULL || *qfmt == '\0')
447 str = headerSprintf(bh, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
451 rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
455 if (ts->transFlags & RPMTRANS_FLAG_ADDINDEPS) {
460 fd = Fopen(str, "r.ufdio");
461 if (fd == NULL || Ferror(fd)) {
462 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), str,
471 rpmrc = rpmReadPackageFile(ts, fd, str, &h);
477 case RPMRC_NOTTRUSTED:
481 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL))
483 rpmMessage(RPMMESS_DEBUG, _("Adding: %s\n"), str);
485 /* XXX str memory leak */
495 rpmMessage(RPMMESS_DEBUG, _("Suggesting: %s\n"), str);
496 /* If suggestion is already present, don't bother. */
497 if (ts->suggests != NULL && ts->nsuggests > 0) {
498 if (bsearch(&str, ts->suggests, ts->nsuggests,
499 sizeof(*ts->suggests), sugcmp))
503 /* Add a new (unique) suggestion. */
504 ts->suggests = xrealloc(ts->suggests,
505 sizeof(*ts->suggests) * (ts->nsuggests + 2));
506 ts->suggests[ts->nsuggests] = str;
508 ts->suggests[ts->nsuggests] = NULL;
510 if (ts->nsuggests > 1)
511 qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp);
514 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
520 int rpmtsAvailable(rpmts ts, const rpmds ds)
523 int rc = 1; /* assume not found */
525 if (ts->availablePackages == NULL)
527 sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL);
531 /* XXX no alternatives yet */
532 if (sugkey[0] != NULL) {
533 ts->suggests = xrealloc(ts->suggests,
534 sizeof(*ts->suggests) * (ts->nsuggests + 2));
535 ts->suggests[ts->nsuggests] = sugkey[0];
538 ts->suggests[ts->nsuggests] = NULL;
540 sugkey = _free(sugkey);
541 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
546 int rpmtsSetSolveCallback(rpmts ts,
547 int (*solve) (rpmts ts, rpmds key, const void * data),
548 const void * solveData)
554 /*@-assignexpose -temptrans @*/
556 ts->solveData = solveData;
557 /*@=assignexpose =temptrans @*/
563 rpmps rpmtsProblems(rpmts ts)
568 ps = rpmpsLink(ts->probs, NULL);
573 void rpmtsCleanDig(rpmts ts)
575 ts->sig = headerFreeData(ts->sig, ts->sigtype);
576 ts->dig = pgpFreeDig(ts->dig);
579 void rpmtsClean(rpmts ts)
586 /* Clean up after dependency checks. */
588 while ((p = rpmtsiNext(pi, 0)) != NULL)
592 ts->addedPackages = rpmalFree(ts->addedPackages);
593 ts->numAddedPackages = 0;
595 ts->suggests = _free(ts->suggests);
598 ts->probs = rpmpsFree(ts->probs);
603 void rpmtsEmpty(rpmts ts)
611 /*@-nullstate@*/ /* FIX: partial annotations */
615 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
616 /*@-type -unqualifiedtrans @*/
617 ts->order[oc] = rpmteFree(ts->order[oc]);
618 /*@=type =unqualifiedtrans @*/
624 ts->numRemovedPackages = 0;
625 /*@-nullstate@*/ /* FIX: partial annotations */
630 rpmts rpmtsFree(rpmts ts)
636 return rpmtsUnlink(ts, "tsCreate");
638 /*@-nullstate@*/ /* FIX: partial annotations */
642 (void) rpmtsCloseDB(ts);
644 (void) rpmtsCloseSDB(ts);
646 ts->removedPackages = _free(ts->removedPackages);
648 ts->availablePackages = rpmalFree(ts->availablePackages);
649 ts->numAvailablePackages = 0;
651 ts->dsi = _free(ts->dsi);
653 if (ts->scriptFd != NULL) {
654 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsFree");
657 ts->rootDir = _free(ts->rootDir);
658 ts->currDir = _free(ts->currDir);
660 /*@-type +voidabstract @*/ /* FIX: double indirection */
661 ts->order = _free(ts->order);
662 /*@=type =voidabstract @*/
663 ts->orderAlloced = 0;
665 if (ts->pkpkt != NULL)
666 ts->pkpkt = _free(ts->pkpkt);
668 memset(ts->pksignid, 0, sizeof(ts->pksignid));
670 (void) rpmtsUnlink(ts, "tsCreate");
672 /*@-refcounttrans -usereleased @*/
674 /*@=refcounttrans =usereleased @*/
679 rpmVSFlags rpmtsVSFlags(rpmts ts)
681 rpmVSFlags vsflags = 0;
683 vsflags = ts->vsflags;
687 rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
689 rpmVSFlags ovsflags = 0;
691 ovsflags = ts->vsflags;
692 ts->vsflags = vsflags;
697 int rpmtsUnorderedSuccessors(rpmts ts, int first)
699 int unorderedSuccessors = 0;
701 unorderedSuccessors = ts->unorderedSuccessors;
703 ts->unorderedSuccessors = first;
705 return unorderedSuccessors;
708 const char * rpmtsRootDir(rpmts ts)
710 return (ts != NULL ? ts->rootDir : NULL);
713 void rpmtsSetRootDir(rpmts ts, const char * rootDir)
718 ts->rootDir = _free(ts->rootDir);
720 if (rootDir == NULL) {
722 ts->rootDir = xstrdup("");
726 rootLen = strlen(rootDir);
729 /* Make sure that rootDir has trailing / */
730 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
731 char * t = alloca(rootLen + 2);
733 (void) stpcpy( stpcpy(t, rootDir), "/");
737 ts->rootDir = xstrdup(rootDir);
741 const char * rpmtsCurrDir(rpmts ts)
743 const char * currDir = NULL;
745 currDir = ts->currDir;
750 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
753 ts->currDir = _free(ts->currDir);
755 ts->currDir = xstrdup(currDir);
759 FD_t rpmtsScriptFd(rpmts ts)
761 FD_t scriptFd = NULL;
763 scriptFd = ts->scriptFd;
765 /*@-compdef -refcounttrans -usereleased@*/
767 /*@=compdef =refcounttrans =usereleased@*/
770 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
774 if (ts->scriptFd != NULL) {
775 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd");
779 if (scriptFd != NULL)
780 ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd");
785 int rpmtsChrootDone(rpmts ts)
789 chrootDone = ts->chrootDone;
794 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
798 ochrootDone = ts->chrootDone;
800 ts->rdb->db_chrootDone = chrootDone;
801 ts->chrootDone = chrootDone;
806 int_32 rpmtsGetTid(rpmts ts)
815 int_32 rpmtsSetTid(rpmts ts, int_32 tid)
825 int_32 rpmtsSigtag(const rpmts ts)
833 int_32 rpmtsSigtype(const rpmts ts)
837 sigtype = ts->sigtype;
841 const void * rpmtsSig(const rpmts ts)
843 const void * sig = NULL;
849 int_32 rpmtsSiglen(const rpmts ts)
857 int rpmtsSetSig(rpmts ts,
858 int_32 sigtag, int_32 sigtype, const void * sig, int_32 siglen)
861 if (ts->sig && ts->sigtype)
862 ts->sig = headerFreeData(ts->sig, ts->sigtype);
864 ts->sigtype = (sig ? sigtype : 0);
865 /*@-assignexpose -kepttrans@*/
867 /*@=assignexpose =kepttrans@*/
873 pgpDig rpmtsDig(rpmts ts)
875 /*@-mods@*/ /* FIX: hide lazy malloc for now */
877 ts->dig = pgpNewDig();
884 pgpDigParams rpmtsSignature(const rpmts ts)
886 pgpDig dig = rpmtsDig(ts);
887 if (dig == NULL) return NULL;
888 /*@-immediatetrans@*/
889 return &dig->signature;
890 /*@=immediatetrans@*/
893 pgpDigParams rpmtsPubkey(const rpmts ts)
895 pgpDig dig = rpmtsDig(ts);
896 if (dig == NULL) return NULL;
897 /*@-immediatetrans@*/
899 /*@=immediatetrans@*/
902 rpmdb rpmtsGetRdb(rpmts ts)
908 /*@-compdef -refcounttrans -usereleased @*/
910 /*@=compdef =refcounttrans =usereleased @*/
913 int rpmtsInitDSI(const rpmts ts)
915 rpmDiskSpaceInfo dsi;
920 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
923 rpmMessage(RPMMESS_DEBUG, _("mounted filesystems:\n"));
924 rpmMessage(RPMMESS_DEBUG,
925 _(" i dev bsize bavail iavail mount point\n"));
927 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
928 if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0)
931 /* Get available space on mounted file systems. */
933 ts->dsi = _free(ts->dsi);
934 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
939 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
940 #if STATFS_IN_SYS_STATVFS
942 memset(&sfb, 0, sizeof(sfb));
943 rc = statvfs(ts->filesystems[i], &sfb);
946 memset(&sfb, 0, sizeof(sfb));
948 /* This platform has the 4-argument version of the statfs call. The last two
949 * should be the size of struct statfs and 0, respectively. The 0 is the
950 * filesystem type, and is always 0 when statfs is called on a mounted
951 * filesystem, as we're doing.
953 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
955 rc = statfs(ts->filesystems[i], &sfb);
961 rc = stat(ts->filesystems[i], &sb);
964 dsi->dev = sb.st_dev;
966 dsi->bsize = sfb.f_bsize;
969 #ifdef STATFS_HAS_F_BAVAIL
970 dsi->bavail = sfb.f_bavail;
972 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
973 * available for non-superusers. f_blocks - f_bfree is probably too big, but
974 * it's about all we can do.
976 dsi->bavail = sfb.f_blocks - sfb.f_bfree;
978 /* XXX Avoid FAT and other file systems that have not inodes. */
979 dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
981 rpmMessage(RPMMESS_DEBUG, _("%5d 0x%04x %5u %12ld %12ld %s\n"),
982 i, (unsigned) dsi->dev, (unsigned) dsi->bsize,
983 (signed long) dsi->bavail, (signed long) dsi->iavail,
989 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
990 uint_32 fileSize, uint_32 prevSize, uint_32 fixupSize,
993 rpmDiskSpaceInfo dsi;
998 while (dsi->bsize && dsi->dev != dev)
1000 if (dsi->bsize == 0)
1006 bneeded = BLOCK_ROUND(fileSize, dsi->bsize);
1013 dsi->bneeded += bneeded;
1014 /*@switchbreak@*/ break;
1017 * FIXME: If two packages share a file (same md5sum), and
1018 * that file is being replaced on disk, will dsi->bneeded get
1019 * adjusted twice? Quite probably!
1022 dsi->bneeded += bneeded;
1023 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
1024 /*@switchbreak@*/ break;
1028 dsi->bneeded -= bneeded;
1029 /*@switchbreak@*/ break;
1032 /*@switchbreak@*/ break;
1036 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
1039 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
1041 rpmDiskSpaceInfo dsi;
1046 if (ts->filesystems == NULL || ts->filesystemCount <= 0)
1052 fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) );
1056 ps = rpmtsProblems(ts);
1057 for (i = 0; i < ts->filesystemCount; i++, dsi++) {
1059 if (dsi->bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
1060 rpmpsAppend(ps, RPMPROB_DISKSPACE,
1061 rpmteNEVR(te), rpmteKey(te),
1062 ts->filesystems[i], NULL, NULL,
1063 (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
1066 if (dsi->iavail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
1067 rpmpsAppend(ps, RPMPROB_DISKNODES,
1068 rpmteNEVR(te), rpmteKey(te),
1069 ts->filesystems[i], NULL, NULL,
1070 (adj_fs_blocks(dsi->ineeded) - dsi->iavail));
1076 void * rpmtsNotify(rpmts ts, rpmte te,
1077 rpmCallbackType what, unsigned long amount, unsigned long total)
1080 if (ts && ts->notify && te) {
1081 assert(!(te->type == TR_ADDED && te->h == NULL));
1082 /*@-type@*/ /* FIX: cast? */
1083 /*@-noeffectuncon @*/ /* FIX: check rc */
1084 ptr = ts->notify(te->h, what, amount, total,
1085 rpmteKey(te), ts->notifyData);
1086 /*@=noeffectuncon @*/
1092 int rpmtsNElements(rpmts ts)
1095 if (ts != NULL && ts->order != NULL) {
1096 nelements = ts->orderCount;
1101 rpmte rpmtsElement(rpmts ts, int ix)
1104 if (ts != NULL && ts->order != NULL) {
1105 if (ix >= 0 && ix < ts->orderCount)
1113 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
1115 return (ts != NULL ? ts->ignoreSet : 0);
1118 rpmtransFlags rpmtsFlags(rpmts ts)
1120 return (ts != NULL ? ts->transFlags : 0);
1123 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
1125 rpmtransFlags otransFlags = 0;
1127 otransFlags = ts->transFlags;
1128 ts->transFlags = transFlags;
1133 Spec rpmtsSpec(rpmts ts)
1135 /*@-compdef -retexpose -usereleased@*/
1137 /*@=compdef =retexpose =usereleased@*/
1140 Spec rpmtsSetSpec(rpmts ts, Spec spec)
1142 Spec ospec = ts->spec;
1143 /*@-assignexpose -temptrans@*/
1145 /*@=assignexpose =temptrans@*/
1149 rpmte rpmtsRelocateElement(rpmts ts)
1151 /*@-compdef -retexpose -usereleased@*/
1152 return ts->relocateElement;
1153 /*@=compdef =retexpose =usereleased@*/
1156 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement)
1158 rpmte orelocateElement = ts->relocateElement;
1159 /*@-assignexpose -temptrans@*/
1160 ts->relocateElement = relocateElement;
1161 /*@=assignexpose =temptrans@*/
1162 return orelocateElement;
1165 uint_32 rpmtsColor(rpmts ts)
1167 return (ts != NULL ? ts->color : 0);
1170 uint_32 rpmtsSetColor(rpmts ts, uint_32 color)
1180 int rpmtsSetNotifyCallback(rpmts ts,
1181 rpmCallbackFunction notify, rpmCallbackData notifyData)
1184 ts->notify = notify;
1185 ts->notifyData = notifyData;
1190 int rpmtsGetKeys(const rpmts ts, fnpyKey ** ep, int * nep)
1194 if (nep) *nep = ts->orderCount;
1199 *ep = e = xmalloc(ts->orderCount * sizeof(*e));
1200 pi = rpmtsiInit(ts);
1201 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1202 switch (rpmteType(p)) {
1204 /*@-dependenttrans@*/
1206 /*@=dependenttrans@*/
1207 /*@switchbreak@*/ break;
1211 /*@switchbreak@*/ break;
1215 pi = rpmtsiFree(pi);
1220 rpmts rpmtsCreate(void)
1224 ts = xcalloc(1, sizeof(*ts));
1225 ts->goal = TSM_UNKNOWN;
1226 ts->filesystemCount = 0;
1227 ts->filesystems = NULL;
1230 ts->solve = rpmtsSolve;
1231 ts->solveData = NULL;
1233 ts->suggests = NULL;
1235 ts->sdbmode = O_RDONLY;
1238 ts->dbmode = O_RDONLY;
1240 ts->scriptFd = NULL;
1241 ts->tid = (int_32) time(NULL);
1244 ts->color = rpmExpandNumeric("%{?_transaction_color}");
1246 ts->numRemovedPackages = 0;
1247 ts->allocedRemovedPackages = ts->delta;
1248 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
1249 sizeof(*ts->removedPackages));
1255 ts->numAddedPackages = 0;
1256 ts->addedPackages = NULL;
1258 ts->numAvailablePackages = 0;
1259 ts->availablePackages = NULL;
1261 ts->orderAlloced = 0;
1270 memset(ts->pksignid, 0, sizeof(ts->pksignid));
1275 return rpmtsLink(ts, "tsCreate");