3 * Routine(s) to handle a "rpmts" transaction sets.
9 #include <rpm/rpmtypes.h>
10 #include <rpm/rpmlib.h> /* rpmReadPackage etc */
11 #include <rpm/rpmurl.h>
12 #include <rpm/rpmmacro.h>
13 #include <rpm/rpmfileutil.h> /* rpmtsOpenDB() needs rpmGetPath */
14 #include <rpm/rpmstring.h>
15 #include <rpm/rpmkeyring.h>
17 #include <rpm/rpmdb.h>
18 #include <rpm/rpmal.h>
19 #include <rpm/rpmds.h>
20 #include <rpm/rpmfi.h>
21 #include <rpm/rpmlog.h>
22 #include <rpm/rpmte.h>
24 #include "rpmio/digest.h"
25 #include "lib/rpmlock.h"
26 #include "lib/rpmts_internal.h"
29 /* XXX FIXME: merge with existing (broken?) tests in system.h */
30 /* portability fiddles */
31 #if STATFS_IN_SYS_STATVFS
32 #include <sys/statvfs.h>
35 # if STATFS_IN_SYS_VFS
38 # if STATFS_IN_SYS_MOUNT
39 # include <sys/mount.h>
41 # if STATFS_IN_SYS_STATFS
42 # include <sys/statfs.h>
50 static void loadKeyring(rpmts ts);
56 rpmts rpmtsUnlink(rpmts ts, const char * msg)
59 fprintf(stderr, "--> ts %p -- %d %s\n", ts, ts->nrefs, msg);
64 rpmts rpmtsLink(rpmts ts, const char * msg)
68 fprintf(stderr, "--> ts %p ++ %d %s\n", ts, ts->nrefs, msg);
72 int rpmtsCloseDB(rpmts ts)
76 if (ts->rdb != NULL) {
77 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET),
78 rpmdbOp(ts->rdb, RPMDB_OP_DBGET));
79 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT),
80 rpmdbOp(ts->rdb, RPMDB_OP_DBPUT));
81 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL),
82 rpmdbOp(ts->rdb, RPMDB_OP_DBDEL));
83 rc = rpmdbClose(ts->rdb);
89 int rpmtsOpenDB(rpmts ts, int dbmode)
93 if (ts->rdb != NULL && ts->dbmode == dbmode)
96 (void) rpmtsCloseDB(ts);
98 /* XXX there's a potential db lock race here. */
101 rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
103 char * dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
105 _("cannot open Packages database in %s\n"), dn);
111 int rpmtsInitDB(rpmts ts, int dbmode)
113 void *lock = rpmtsAcquireLock(ts);
116 rc = rpmdbInit(ts->rootDir, dbmode);
121 int rpmtsGetDBMode(rpmts ts)
127 int rpmtsSetDBMode(rpmts ts, int dbmode)
130 /* mode setting only permitted on non-open db */
131 if (ts != NULL && rpmtsGetRdb(ts) == NULL) {
139 int rpmtsRebuildDB(rpmts ts)
142 void *lock = rpmtsAcquireLock(ts);
143 if (!lock) return -1;
144 if (!(ts->vsflags & RPMVSF_NOHDRCHK))
145 rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
147 rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
152 int rpmtsVerifyDB(rpmts ts)
154 return rpmdbVerify(ts->rootDir);
157 /* keyp might no be defined. */
158 rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
159 const void * keyp, size_t keylen)
161 rpmdbMatchIterator mi = NULL;
162 const char * arch = NULL;
166 if (ts->keyring == NULL)
169 if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
172 /* Parse out "N(EVR).A" tokens from a label key. */
173 if (rpmtag == RPMDBI_LABEL && keyp != NULL) {
174 const char *se, *s = keyp;
176 size_t slen = strlen(s);
180 tmp = xmalloc(slen+1);
182 while ((c = *s++) != '\0') {
188 /* XXX Fail if nested parens. */
190 rpmlog(RPMLOG_ERR, _("extra '(' in package label: %s\n"), (const char*)keyp);
193 /* Parse explicit epoch. */
194 for (se = s; *se && risdigit(*se); se++)
197 /* XXX skip explicit epoch's (for now) */
201 /* No Epoch: found. Convert '(' to '-' and chug. */
206 /* XXX Fail if nested parens. */
208 rpmlog(RPMLOG_ERR, _("missing '(' in package label: %s\n"), (const char*)keyp);
211 /* Don't copy trailing ')' */
216 rpmlog(RPMLOG_ERR, _("missing ')' in package label: %s\n"), (const char*)keyp);
222 /* Is this a valid ".arch" suffix? */
223 if (t != NULL && rpmIsKnownArch(t+1)) {
229 mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
231 /* Verify header signature/digest during retrieve (if not disabled). */
232 if (mi && !(ts->vsflags & RPMVSF_NOHDRCHK))
233 (void) rpmdbSetHdrChk(mi, ts, headerCheck);
235 /* Select specified arch only. */
237 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch);
245 rpmKeyring rpmtsGetKeyring(rpmts ts, int autoload)
247 rpmKeyring keyring = NULL;
249 if (ts->keyring == NULL && autoload) {
252 keyring = ts->keyring;
254 return rpmKeyringLink(keyring);
257 int rpmtsSetKeyring(rpmts ts, rpmKeyring keyring)
260 * Should we permit switching keyring on the fly? For now, require
261 * rpmdb isn't open yet (fairly arbitrary limitation)...
263 if (ts == NULL || rpmtsGetRdb(ts) != NULL)
266 rpmKeyringFree(ts->keyring);
267 ts->keyring = rpmKeyringLink(keyring);
271 static int loadKeyringFromFiles(rpmts ts)
274 /* XXX TODO: deal with chroot path issues */
275 char *pkpath = rpmGetPath(ts->rootDir, "%{_keyringpath}/*.key", NULL);
278 rpmlog(RPMLOG_DEBUG, "loading keyring from pubkeys in %s\n", pkpath);
279 if (rpmGlob(pkpath, NULL, &files)) {
280 rpmlog(RPMLOG_DEBUG, "couldn't find any keys in %s\n", pkpath);
284 for (char **f = files; *f; f++) {
285 rpmPubkey key = rpmPubkeyRead(*f);
287 rpmlog(RPMLOG_ERR, _("%s: reading of public key failed.\n"), *f);
290 if (rpmKeyringAddKey(ts->keyring, key) == 0) {
292 rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", *f);
302 static int loadKeyringFromDB(rpmts ts)
305 rpmdbMatchIterator mi;
308 rpmlog(RPMLOG_DEBUG, "loading keyring from rpmdb\n");
309 mi = rpmtsInitIterator(ts, RPMTAG_NAME, "gpg-pubkey", 0);
310 while ((h = rpmdbNextIterator(mi)) != NULL) {
311 struct rpmtd_s pubkeys;
314 if (!headerGet(h, RPMTAG_PUBKEYS, &pubkeys, HEADERGET_MINMEM))
317 while ((key = rpmtdNextString(&pubkeys))) {
321 if (b64decode(key, (void **) &pkt, &pktlen) == 0) {
322 rpmPubkey key = rpmPubkeyNew(pkt, pktlen);
323 if (rpmKeyringAddKey(ts->keyring, key) == 0) {
324 char *nvr = headerGetNEVR(h, NULL);
325 rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", nvr);
333 rpmtdFreeData(&pubkeys);
335 rpmdbFreeIterator(mi);
340 static void loadKeyring(rpmts ts)
342 ts->keyring = rpmKeyringNew();
343 if (loadKeyringFromFiles(ts) == 0) {
344 if (loadKeyringFromDB(ts) > 0) {
345 /* XXX make this a warning someday... */
346 rpmlog(RPMLOG_DEBUG, "Using legacy gpg-pubkey(s) from rpmdb\n");
351 rpmRC rpmtsFindPubkey(rpmts ts, pgpDig dig)
353 rpmRC res = RPMRC_NOKEY;
358 if (ts->keyring == NULL) {
361 res = rpmKeyringLookup(ts->keyring, dig);
367 /* Build pubkey header. */
368 static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header h)
370 const char * afmt = "%{pubkeys:armor}";
371 const char * group = "Public Keys";
372 const char * license = "pubkey";
373 const char * buildhost = "localhost";
374 rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
377 pgpDigParams pubp = NULL;
387 if ((enc = rpmPubkeyBase64(key)) == NULL)
389 if ((dig = rpmPubkeyDig(key)) == NULL)
392 /* Build header elements. */
394 v = pgpHexStr(pubp->signid, sizeof(pubp->signid));
395 r = pgpHexStr(pubp->time, sizeof(pubp->time));
397 rasprintf(&n, "gpg(%s)", v+8);
398 rasprintf(&u, "gpg(%s)", pubp->userid ? pubp->userid : "none");
399 rasprintf(&evr, "%d:%s-%s", pubp->version, v, r);
401 headerPutString(h, RPMTAG_PUBKEYS, enc);
403 if ((d = headerFormat(h, afmt, NULL)) == NULL)
406 headerPutString(h, RPMTAG_NAME, "gpg-pubkey");
407 headerPutString(h, RPMTAG_VERSION, v+8);
408 headerPutString(h, RPMTAG_RELEASE, r);
409 headerPutString(h, RPMTAG_DESCRIPTION, d);
410 headerPutString(h, RPMTAG_GROUP, group);
411 headerPutString(h, RPMTAG_LICENSE, license);
412 headerPutString(h, RPMTAG_SUMMARY, u);
414 headerPutUint32(h, RPMTAG_SIZE, &zero, 1);
416 headerPutString(h, RPMTAG_PROVIDENAME, u);
417 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
418 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
420 headerPutString(h, RPMTAG_PROVIDENAME, n);
421 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
422 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
424 headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION);
425 headerPutString(h, RPMTAG_BUILDHOST, buildhost);
427 { rpm_tid_t tid = rpmtsGetTid(ts);
428 headerPutUint32(h, RPMTAG_INSTALLTIME, &tid, 1);
429 headerPutUint32(h, RPMTAG_BUILDTIME, &tid, 1);
446 rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen)
448 Header h = headerNew();
449 rpmRC rc = RPMRC_FAIL; /* assume failure */
450 rpmPubkey pubkey = NULL;
451 rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
453 if ((pubkey = rpmPubkeyNew(pkt, pktlen)) == NULL)
455 if (rpmKeyringAddKey(keyring, pubkey) != 0)
457 if (makePubkeyHeader(ts, pubkey, h) != 0)
460 /* Add header to database. */
461 if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
463 if (rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL, NULL) != 0)
470 rpmPubkeyFree(pubkey);
471 rpmKeyringFree(keyring);
475 int rpmtsSetSolveCallback(rpmts ts,
476 int (*solve) (rpmts ts, rpmds key, const void * data),
477 const void * solveData)
483 ts->solveData = solveData;
488 rpmps rpmtsProblems(rpmts ts)
493 ps = rpmpsLink(ts->probs, RPMDBG_M("rpmtsProblems"));
498 void rpmtsCleanProblems(rpmts ts)
500 if (ts && ts->probs) {
501 ts->probs = rpmpsFree(ts->probs);
505 void rpmtsClean(rpmts ts)
512 /* Clean up after dependency checks. */
514 while ((p = rpmtsiNext(pi, 0)) != NULL)
518 ts->addedPackages = rpmalFree(ts->addedPackages);
519 ts->numAddedPackages = 0;
521 rpmtsCleanProblems(ts);
524 void rpmtsEmpty(rpmts ts)
531 for (int oc = 0; oc < ts->orderCount; oc++) {
532 ts->order[oc] = rpmteFree(ts->order[oc]);
539 ts->numRemovedPackages = 0;
543 static void rpmtsPrintStat(const char * name, struct rpmop_s * op)
545 static const unsigned int scale = (1000 * 1000);
546 if (op != NULL && op->count > 0)
547 fprintf(stderr, " %s %6d %6lu.%06lu MB %6lu.%06lu secs\n",
549 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
550 op->usecs/scale, op->usecs%scale);
553 static void rpmtsPrintStats(rpmts ts)
555 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
557 rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL));
558 rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK));
559 rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER));
560 rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
561 rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL));
562 rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE));
563 rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
564 rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
565 rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
566 rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST));
567 rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
568 rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD));
569 rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
570 rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET));
571 rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT));
572 rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL));
575 rpmts rpmtsFree(rpmts ts)
581 return rpmtsUnlink(ts, RPMDBG_M("tsCreate"));
585 (void) rpmtsCloseDB(ts);
587 ts->removedPackages = _free(ts->removedPackages);
589 ts->dsi = _free(ts->dsi);
591 if (ts->scriptFd != NULL) {
592 ts->scriptFd = fdFree(ts->scriptFd, RPMDBG_M("rpmtsFree"));
595 ts->rootDir = _free(ts->rootDir);
596 ts->currDir = _free(ts->currDir);
598 ts->order = _free(ts->order);
599 ts->orderAlloced = 0;
601 ts->keyring = rpmKeyringFree(ts->keyring);
602 ts->netsharedPaths = argvFree(ts->netsharedPaths);
603 ts->installLangs = argvFree(ts->installLangs);
608 (void) rpmtsUnlink(ts, RPMDBG_M("tsCreate"));
615 rpmVSFlags rpmtsVSFlags(rpmts ts)
617 rpmVSFlags vsflags = 0;
619 vsflags = ts->vsflags;
623 rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
625 rpmVSFlags ovsflags = 0;
627 ovsflags = ts->vsflags;
628 ts->vsflags = vsflags;
633 int rpmtsUnorderedSuccessors(rpmts ts, int first)
635 int unorderedSuccessors = 0;
637 unorderedSuccessors = ts->unorderedSuccessors;
639 ts->unorderedSuccessors = first;
641 return unorderedSuccessors;
644 const char * rpmtsRootDir(rpmts ts)
646 const char * rootDir = NULL;
648 if (ts != NULL && ts->rootDir != NULL) {
649 urltype ut = urlPath(ts->rootDir, &rootDir);
654 /* XXX these shouldn't be allowed as rootdir! */
668 int rpmtsSetRootDir(rpmts ts, const char * rootDir)
670 if (ts == NULL || (rootDir && rootDir[0] != '/')) {
674 ts->rootDir = _free(ts->rootDir);
675 /* Ensure clean path with a trailing slash */
676 ts->rootDir = rootDir ? rpmGetPath(rootDir, NULL) : xstrdup("/");
677 if (strcmp(ts->rootDir, "/") != 0) {
678 rstrcat(&ts->rootDir, "/");
683 const char * rpmtsCurrDir(rpmts ts)
685 const char * currDir = NULL;
687 currDir = ts->currDir;
692 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
695 ts->currDir = _free(ts->currDir);
697 ts->currDir = xstrdup(currDir);
701 FD_t rpmtsScriptFd(rpmts ts)
703 FD_t scriptFd = NULL;
705 scriptFd = ts->scriptFd;
710 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
714 if (ts->scriptFd != NULL) {
715 ts->scriptFd = fdFree(ts->scriptFd,
716 RPMDBG_M("rpmtsSetScriptFd"));
719 if (scriptFd != NULL)
720 ts->scriptFd = fdLink((void *)scriptFd,
721 RPMDBG_M("rpmtsSetScriptFd"));
725 int rpmtsSELinuxEnabled(rpmts ts)
727 return (ts != NULL ? (ts->selinuxEnabled > 0) : 0);
730 int rpmtsChrootDone(rpmts ts)
732 return (ts != NULL ? ts->chrootDone : 0);
735 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
739 ochrootDone = ts->chrootDone;
740 rpmdbSetChrootDone(rpmtsGetRdb(ts), chrootDone);
741 ts->chrootDone = chrootDone;
746 rpm_tid_t rpmtsGetTid(rpmts ts)
748 rpm_tid_t tid = -1; /* XXX -1 is time(2) error return. */
755 rpm_tid_t rpmtsSetTid(rpmts ts, rpm_tid_t tid)
757 rpm_tid_t otid = -1; /* XXX -1 is time(2) error return. */
765 rpmdb rpmtsGetRdb(rpmts ts)
774 int rpmtsInitDSI(const rpmts ts)
776 rpmDiskSpaceInfo dsi;
781 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
784 rpmlog(RPMLOG_DEBUG, "mounted filesystems:\n");
786 " i dev bsize bavail iavail mount point\n");
788 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
789 if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0)
792 /* Get available space on mounted file systems. */
794 ts->dsi = _free(ts->dsi);
795 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
800 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
801 #if STATFS_IN_SYS_STATVFS
803 memset(&sfb, 0, sizeof(sfb));
804 rc = statvfs(ts->filesystems[i], &sfb);
807 memset(&sfb, 0, sizeof(sfb));
809 /* This platform has the 4-argument version of the statfs call. The last two
810 * should be the size of struct statfs and 0, respectively. The 0 is the
811 * filesystem type, and is always 0 when statfs is called on a mounted
812 * filesystem, as we're doing.
814 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
816 rc = statfs(ts->filesystems[i], &sfb);
822 rc = stat(ts->filesystems[i], &sb);
825 dsi->dev = sb.st_dev;
827 dsi->bsize = sfb.f_bsize;
830 #ifdef STATFS_HAS_F_BAVAIL
831 dsi->bavail = sfb.f_bavail;
833 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
834 * available for non-superusers. f_blocks - f_bfree is probably too big, but
835 * it's about all we can do.
837 dsi->bavail = sfb.f_blocks - sfb.f_bfree;
839 /* XXX Avoid FAT and other file systems that have not inodes. */
840 /* XXX assigning negative value to unsigned type */
841 dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
844 "%5d 0x%08x %8" PRId64 " %12" PRId64 " %12" PRId64" %s\n",
845 i, (unsigned) dsi->dev, dsi->bsize,
846 dsi->bavail, dsi->iavail,
852 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
853 rpm_loff_t fileSize, rpm_loff_t prevSize, rpm_loff_t fixupSize,
854 rpmFileAction action)
856 rpmDiskSpaceInfo dsi;
861 while (dsi->bsize && dsi->dev != dev)
869 bneeded = BLOCK_ROUND(fileSize, dsi->bsize);
876 dsi->bneeded += bneeded;
880 * FIXME: If two packages share a file (same md5sum), and
881 * that file is being replaced on disk, will dsi->bneeded get
882 * adjusted twice? Quite probably!
885 dsi->bneeded += bneeded;
886 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
891 dsi->bneeded -= bneeded;
899 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
902 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
904 rpmDiskSpaceInfo dsi;
909 if (ts->filesystems == NULL || ts->filesystemCount <= 0)
915 fc = rpmfiFC(rpmteFI(te));
919 ps = rpmtsProblems(ts);
920 for (i = 0; i < ts->filesystemCount; i++, dsi++) {
922 if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
923 rpmpsAppend(ps, RPMPROB_DISKSPACE,
924 rpmteNEVRA(te), rpmteKey(te),
925 ts->filesystems[i], NULL, NULL,
926 (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
929 if (dsi->iavail >= 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
930 rpmpsAppend(ps, RPMPROB_DISKNODES,
931 rpmteNEVRA(te), rpmteKey(te),
932 ts->filesystems[i], NULL, NULL,
933 (adj_fs_blocks(dsi->ineeded) - dsi->iavail));
939 void * rpmtsNotify(rpmts ts, rpmte te,
940 rpmCallbackType what, rpm_loff_t amount, rpm_loff_t total)
943 if (ts && ts->notify) {
945 fnpyKey cbkey = NULL;
948 cbkey = rpmteKey(te);
950 ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData);
953 headerUnlink(h); /* undo rpmteHeader() ref */
959 int rpmtsNElements(rpmts ts)
962 if (ts != NULL && ts->order != NULL) {
963 nelements = ts->orderCount;
968 rpmte rpmtsElement(rpmts ts, int ix)
971 if (ts != NULL && ts->order != NULL) {
972 if (ix >= 0 && ix < ts->orderCount)
978 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
980 return (ts != NULL ? ts->ignoreSet : 0);
983 rpmtransFlags rpmtsFlags(rpmts ts)
985 return (ts != NULL ? ts->transFlags : 0);
988 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
990 rpmtransFlags otransFlags = 0;
992 otransFlags = ts->transFlags;
993 ts->transFlags = transFlags;
998 rpmSpec rpmtsSpec(rpmts ts)
1003 rpmSpec rpmtsSetSpec(rpmts ts, rpmSpec spec)
1005 rpmSpec ospec = ts->spec;
1010 rpmte rpmtsRelocateElement(rpmts ts)
1012 return ts->relocateElement;
1015 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement)
1017 rpmte orelocateElement = ts->relocateElement;
1018 ts->relocateElement = relocateElement;
1019 return orelocateElement;
1022 rpm_color_t rpmtsColor(rpmts ts)
1024 return (ts != NULL ? ts->color : 0);
1027 rpm_color_t rpmtsSetColor(rpmts ts, rpm_color_t color)
1029 rpm_color_t ocolor = 0;
1037 rpm_color_t rpmtsPrefColor(rpmts ts)
1039 return (ts != NULL ? ts->prefcolor : 0);
1042 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
1046 if (ts != NULL && opx >= 0 && opx < RPMTS_OP_MAX)
1051 int rpmtsSetNotifyCallback(rpmts ts,
1052 rpmCallbackFunction notify, rpmCallbackData notifyData)
1055 ts->notify = notify;
1056 ts->notifyData = notifyData;
1061 int rpmtsGetKeys(const rpmts ts, fnpyKey ** ep, int * nep)
1065 if (nep) *nep = ts->orderCount;
1070 *ep = e = xmalloc(ts->orderCount * sizeof(*e));
1071 pi = rpmtsiInit(ts);
1072 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1073 switch (rpmteType(p)) {
1084 pi = rpmtsiFree(pi);
1089 rpmts rpmtsCreate(void)
1093 ts = xcalloc(1, sizeof(*ts));
1094 memset(&ts->ops, 0, sizeof(ts->ops));
1095 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
1096 ts->filesystemCount = 0;
1097 ts->filesystems = NULL;
1101 ts->solveData = NULL;
1104 ts->dbmode = O_RDONLY;
1106 ts->scriptFd = NULL;
1107 ts->tid = (rpm_tid_t) time(NULL);
1110 ts->color = rpmExpandNumeric("%{?_transaction_color}");
1111 ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}")?:2;
1113 ts->netsharedPaths = NULL;
1114 ts->installLangs = NULL;
1115 { char *tmp = rpmExpand("%{_netsharedpath}", NULL);
1116 if (tmp && *tmp != '%') {
1117 argvSplit(&ts->netsharedPaths, tmp, ":");
1121 tmp = rpmExpand("%{_install_langs}", NULL);
1122 if (tmp && *tmp != '%') {
1123 ARGV_t langs = NULL;
1124 argvSplit(&langs, tmp, ":");
1125 /* If we'll be installing all languages anyway, don't bother */
1126 for (ARGV_t l = langs; *l; l++) {
1127 if (strcmp(*l, "all") == 0) {
1128 langs = argvFree(langs);
1132 ts->installLangs = langs;
1137 ts->numRemovedPackages = 0;
1138 ts->allocedRemovedPackages = ts->delta;
1139 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
1140 sizeof(*ts->removedPackages));
1146 ts->selinuxEnabled = is_selinux_enabled();
1148 ts->numAddedPackages = 0;
1149 ts->addedPackages = NULL;
1151 ts->orderAlloced = 0;
1163 return rpmtsLink(ts, RPMDBG_M("tsCreate"));