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/rpmds.h>
19 #include <rpm/rpmfi.h>
20 #include <rpm/rpmlog.h>
21 #include <rpm/rpmte.h>
23 #include "rpmio/digest.h"
24 #include "lib/rpmal.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 = rpmKeyringLink(ts->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 = headerGetAsString(h, RPMTAG_NVR);
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);
426 headerPutString(h, RPMTAG_SOURCERPM, "(none)");
428 { rpm_tid_t tid = rpmtsGetTid(ts);
429 headerPutUint32(h, RPMTAG_INSTALLTIME, &tid, 1);
430 headerPutUint32(h, RPMTAG_BUILDTIME, &tid, 1);
447 rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen)
449 Header h = headerNew();
450 rpmRC rc = RPMRC_FAIL; /* assume failure */
451 rpmPubkey pubkey = NULL;
452 rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
454 if ((pubkey = rpmPubkeyNew(pkt, pktlen)) == NULL)
456 if (rpmKeyringAddKey(keyring, pubkey) != 0)
458 if (makePubkeyHeader(ts, pubkey, h) != 0)
461 /* Add header to database. */
462 if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
464 if (rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL, NULL) != 0)
471 rpmPubkeyFree(pubkey);
472 rpmKeyringFree(keyring);
476 int rpmtsSetSolveCallback(rpmts ts,
477 int (*solve) (rpmts ts, rpmds key, const void * data),
478 const void * solveData)
484 ts->solveData = solveData;
489 rpmps rpmtsProblems(rpmts ts)
494 ps = rpmpsLink(ts->probs, RPMDBG_M("rpmtsProblems"));
499 void rpmtsCleanProblems(rpmts ts)
501 if (ts && ts->probs) {
502 ts->probs = rpmpsFree(ts->probs);
506 void rpmtsClean(rpmts ts)
513 /* Clean up after dependency checks. */
515 while ((p = rpmtsiNext(pi, 0)) != NULL)
519 ts->addedPackages = rpmalFree(ts->addedPackages);
520 ts->numAddedPackages = 0;
522 rpmtsCleanProblems(ts);
525 void rpmtsEmpty(rpmts ts)
532 for (int oc = 0; oc < ts->orderCount; oc++) {
533 ts->order[oc] = rpmteFree(ts->order[oc]);
540 ts->numRemovedPackages = 0;
544 static void rpmtsPrintStat(const char * name, struct rpmop_s * op)
546 static const unsigned int scale = (1000 * 1000);
547 if (op != NULL && op->count > 0)
548 fprintf(stderr, " %s %6d %6lu.%06lu MB %6lu.%06lu secs\n",
550 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
551 op->usecs/scale, op->usecs%scale);
554 static void rpmtsPrintStats(rpmts ts)
556 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
558 rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL));
559 rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK));
560 rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER));
561 rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
562 rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL));
563 rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE));
564 rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
565 rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
566 rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
567 rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST));
568 rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
569 rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD));
570 rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
571 rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET));
572 rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT));
573 rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL));
576 rpmts rpmtsFree(rpmts ts)
582 return rpmtsUnlink(ts, RPMDBG_M("tsCreate"));
586 (void) rpmtsCloseDB(ts);
588 ts->removedPackages = _free(ts->removedPackages);
590 ts->dsi = _free(ts->dsi);
592 if (ts->scriptFd != NULL) {
593 ts->scriptFd = fdFree(ts->scriptFd, RPMDBG_M("rpmtsFree"));
596 ts->rootDir = _free(ts->rootDir);
597 ts->currDir = _free(ts->currDir);
599 ts->order = _free(ts->order);
600 ts->orderAlloced = 0;
602 ts->keyring = rpmKeyringFree(ts->keyring);
603 ts->netsharedPaths = argvFree(ts->netsharedPaths);
604 ts->installLangs = argvFree(ts->installLangs);
609 (void) rpmtsUnlink(ts, RPMDBG_M("tsCreate"));
616 rpmVSFlags rpmtsVSFlags(rpmts ts)
618 rpmVSFlags vsflags = 0;
620 vsflags = ts->vsflags;
624 rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
626 rpmVSFlags ovsflags = 0;
628 ovsflags = ts->vsflags;
629 ts->vsflags = vsflags;
634 const char * rpmtsRootDir(rpmts ts)
636 const char * rootDir = NULL;
638 if (ts != NULL && ts->rootDir != NULL) {
639 urltype ut = urlPath(ts->rootDir, &rootDir);
644 /* XXX these shouldn't be allowed as rootdir! */
658 int rpmtsSetRootDir(rpmts ts, const char * rootDir)
660 if (ts == NULL || (rootDir && rootDir[0] != '/')) {
664 ts->rootDir = _free(ts->rootDir);
665 /* Ensure clean path with a trailing slash */
666 ts->rootDir = rootDir ? rpmGetPath(rootDir, NULL) : xstrdup("/");
667 if (!rstreq(ts->rootDir, "/")) {
668 rstrcat(&ts->rootDir, "/");
673 const char * rpmtsCurrDir(rpmts ts)
675 const char * currDir = NULL;
677 currDir = ts->currDir;
682 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
685 ts->currDir = _free(ts->currDir);
687 ts->currDir = xstrdup(currDir);
691 FD_t rpmtsScriptFd(rpmts ts)
693 FD_t scriptFd = NULL;
695 scriptFd = ts->scriptFd;
700 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
704 if (ts->scriptFd != NULL) {
705 ts->scriptFd = fdFree(ts->scriptFd,
706 RPMDBG_M("rpmtsSetScriptFd"));
709 if (scriptFd != NULL)
710 ts->scriptFd = fdLink((void *)scriptFd,
711 RPMDBG_M("rpmtsSetScriptFd"));
715 int rpmtsSELinuxEnabled(rpmts ts)
717 return (ts != NULL ? (ts->selinuxEnabled > 0) : 0);
720 int rpmtsChrootDone(rpmts ts)
722 return (ts != NULL ? ts->chrootDone : 0);
725 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
729 ochrootDone = ts->chrootDone;
730 rpmdbSetChrootDone(rpmtsGetRdb(ts), chrootDone);
731 ts->chrootDone = chrootDone;
736 rpm_tid_t rpmtsGetTid(rpmts ts)
738 rpm_tid_t tid = (rpm_tid_t)-1; /* XXX -1 is time(2) error return. */
745 rpm_tid_t rpmtsSetTid(rpmts ts, rpm_tid_t tid)
747 rpm_tid_t otid = (rpm_tid_t)-1; /* XXX -1 is time(2) error return. */
755 rpmdb rpmtsGetRdb(rpmts ts)
764 int rpmtsInitDSI(const rpmts ts)
766 rpmDiskSpaceInfo dsi;
771 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
774 rpmlog(RPMLOG_DEBUG, "mounted filesystems:\n");
776 " i dev bsize bavail iavail mount point\n");
778 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
779 if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0)
782 /* Get available space on mounted file systems. */
784 ts->dsi = _free(ts->dsi);
785 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
790 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
791 #if STATFS_IN_SYS_STATVFS
793 memset(&sfb, 0, sizeof(sfb));
794 rc = statvfs(ts->filesystems[i], &sfb);
797 memset(&sfb, 0, sizeof(sfb));
799 /* This platform has the 4-argument version of the statfs call. The last two
800 * should be the size of struct statfs and 0, respectively. The 0 is the
801 * filesystem type, and is always 0 when statfs is called on a mounted
802 * filesystem, as we're doing.
804 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
806 rc = statfs(ts->filesystems[i], &sfb);
812 rc = stat(ts->filesystems[i], &sb);
815 dsi->dev = sb.st_dev;
817 dsi->bsize = sfb.f_bsize;
820 #ifdef STATFS_HAS_F_BAVAIL
821 dsi->bavail = sfb.f_bavail;
823 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
824 * available for non-superusers. f_blocks - f_bfree is probably too big, but
825 * it's about all we can do.
827 dsi->bavail = sfb.f_blocks - sfb.f_bfree;
829 /* XXX Avoid FAT and other file systems that have not inodes. */
830 /* XXX assigning negative value to unsigned type */
831 dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
834 "%5d 0x%08x %8" PRId64 " %12" PRId64 " %12" PRId64" %s\n",
835 i, (unsigned) dsi->dev, dsi->bsize,
836 dsi->bavail, dsi->iavail,
842 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
843 rpm_loff_t fileSize, rpm_loff_t prevSize, rpm_loff_t fixupSize,
844 rpmFileAction action)
846 rpmDiskSpaceInfo dsi;
851 while (dsi->bsize && dsi->dev != dev)
859 bneeded = BLOCK_ROUND(fileSize, dsi->bsize);
866 dsi->bneeded += bneeded;
870 * FIXME: If two packages share a file (same md5sum), and
871 * that file is being replaced on disk, will dsi->bneeded get
872 * adjusted twice? Quite probably!
875 dsi->bneeded += bneeded;
876 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
881 dsi->bneeded -= bneeded;
889 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
892 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
894 rpmDiskSpaceInfo dsi;
899 if (ts->filesystems == NULL || ts->filesystemCount <= 0)
905 fc = rpmfiFC(rpmteFI(te));
909 ps = rpmtsProblems(ts);
910 for (i = 0; i < ts->filesystemCount; i++, dsi++) {
912 if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
913 rpmpsAppend(ps, RPMPROB_DISKSPACE,
914 rpmteNEVRA(te), rpmteKey(te),
915 ts->filesystems[i], NULL, NULL,
916 (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
919 if (dsi->iavail >= 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
920 rpmpsAppend(ps, RPMPROB_DISKNODES,
921 rpmteNEVRA(te), rpmteKey(te),
922 ts->filesystems[i], NULL, NULL,
923 (adj_fs_blocks(dsi->ineeded) - dsi->iavail));
929 void * rpmtsNotify(rpmts ts, rpmte te,
930 rpmCallbackType what, rpm_loff_t amount, rpm_loff_t total)
933 if (ts && ts->notify) {
935 fnpyKey cbkey = NULL;
938 cbkey = rpmteKey(te);
940 ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData);
943 headerUnlink(h); /* undo rpmteHeader() ref */
949 int rpmtsNElements(rpmts ts)
952 if (ts != NULL && ts->order != NULL) {
953 nelements = ts->orderCount;
958 rpmte rpmtsElement(rpmts ts, int ix)
961 if (ts != NULL && ts->order != NULL) {
962 if (ix >= 0 && ix < ts->orderCount)
968 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
970 return (ts != NULL ? ts->ignoreSet : 0);
973 rpmtransFlags rpmtsFlags(rpmts ts)
975 return (ts != NULL ? ts->transFlags : 0);
978 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
980 rpmtransFlags otransFlags = 0;
982 otransFlags = ts->transFlags;
983 ts->transFlags = transFlags;
988 rpmSpec rpmtsSpec(rpmts ts)
993 rpmSpec rpmtsSetSpec(rpmts ts, rpmSpec spec)
995 rpmSpec ospec = ts->spec;
1000 rpm_color_t rpmtsColor(rpmts ts)
1002 return (ts != NULL ? ts->color : 0);
1005 rpm_color_t rpmtsSetColor(rpmts ts, rpm_color_t color)
1007 rpm_color_t ocolor = 0;
1015 rpm_color_t rpmtsPrefColor(rpmts ts)
1017 return (ts != NULL ? ts->prefcolor : 0);
1020 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
1024 if (ts != NULL && opx >= 0 && opx < RPMTS_OP_MAX)
1029 int rpmtsSetNotifyCallback(rpmts ts,
1030 rpmCallbackFunction notify, rpmCallbackData notifyData)
1033 ts->notify = notify;
1034 ts->notifyData = notifyData;
1039 int rpmtsGetKeys(const rpmts ts, fnpyKey ** ep, int * nep)
1043 if (nep) *nep = ts->orderCount;
1048 *ep = e = xmalloc(ts->orderCount * sizeof(*e));
1049 pi = rpmtsiInit(ts);
1050 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1051 switch (rpmteType(p)) {
1062 pi = rpmtsiFree(pi);
1067 rpmts rpmtsCreate(void)
1071 ts = xcalloc(1, sizeof(*ts));
1072 memset(&ts->ops, 0, sizeof(ts->ops));
1073 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
1074 ts->filesystemCount = 0;
1075 ts->filesystems = NULL;
1079 ts->solveData = NULL;
1082 ts->dbmode = O_RDONLY;
1084 ts->scriptFd = NULL;
1085 ts->tid = (rpm_tid_t) time(NULL);
1088 ts->color = rpmExpandNumeric("%{?_transaction_color}");
1089 ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}")?:2;
1091 ts->netsharedPaths = NULL;
1092 ts->installLangs = NULL;
1093 { char *tmp = rpmExpand("%{_netsharedpath}", NULL);
1094 if (tmp && *tmp != '%') {
1095 argvSplit(&ts->netsharedPaths, tmp, ":");
1099 tmp = rpmExpand("%{_install_langs}", NULL);
1100 if (tmp && *tmp != '%') {
1101 ARGV_t langs = NULL;
1102 argvSplit(&langs, tmp, ":");
1103 /* If we'll be installing all languages anyway, don't bother */
1104 for (ARGV_t l = langs; *l; l++) {
1105 if (rstreq(*l, "all")) {
1106 langs = argvFree(langs);
1110 ts->installLangs = langs;
1115 ts->numRemovedPackages = 0;
1116 ts->allocedRemovedPackages = ts->delta;
1117 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
1118 sizeof(*ts->removedPackages));
1124 ts->selinuxEnabled = is_selinux_enabled();
1126 ts->numAddedPackages = 0;
1127 ts->addedPackages = NULL;
1129 ts->orderAlloced = 0;
1141 return rpmtsLink(ts, RPMDBG_M("tsCreate"));