rpm 5.2.1

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

- File List
- Globals

rpmts.c
Go to the documentation of this file.
1
5 #include "system.h"
6
7 #include <rpmio.h>
8 #include <rpmiotypes.h> /* XXX fnpyKey */
9 #include <rpmlog.h>
10 #include <iosm.h> /* XXX iosmFileAction */
11 #include <rpmurl.h>
12 #include <rpmpgp.h>
13 #include <rpmmacro.h> /* XXX rpmtsOpenDB() needs rpmGetPath */
14 #include <rpmkeyring.h>
15
16 #include <rpmtypes.h>
17 #include <rpmtag.h>
18 #include <pkgio.h>
19
20 #define _RPMDB_INTERNAL /* XXX almost opaque sigh */
21 #include "rpmdb.h" /* XXX stealing db->db_mode. */
22
23 #include "rpmal.h"
24 #include "rpmds.h"
25 #include "rpmfi.h"
26 #include "rpmlock.h"
27 #include "rpmns.h"
28
29 #define _RPMTE_INTERNAL /* XXX te->h */
30 #include "rpmte.h"
31
32 #define _RPMTS_INTERNAL
33 #include "rpmts.h"
34
35 #include <rpmcli.h>
36
37 #include "fs.h"
38
39 /* XXX FIXME: merge with existing (broken?) tests in system.h */
40 /* portability fiddles */
41 #if STATFS_IN_SYS_STATVFS
42 /*@-incondefs@*/
43 #if defined(__LCLINT__)
44 /*@-declundef -exportheader -protoparammatch @*/ /* LCL: missing annotation */
45 extern int statvfs (const char * file, /*@out@*/ struct statvfs * buf)
46 /*@globals fileSystem @*/
47 /*@modifies *buf, fileSystem @*/;
48 /*@=declundef =exportheader =protoparammatch @*/
49 /*@=incondefs@*/
50 #else
51 # include <sys/statvfs.h>
52 #endif
53 #else
54 # if STATFS_IN_SYS_VFS
55 # include <sys/vfs.h>
56 # else
57 # if STATFS_IN_SYS_MOUNT
58 # include <sys/mount.h>
59 # else
60 # if STATFS_IN_SYS_STATFS
61 # include <sys/statfs.h>
62 # endif
63 # endif
64 # endif
65 #endif
66
67 #include "debug.h"
68
69 /*@access FD_t @*/ /* XXX void * arg */
70 /*@access rpmdb @*/ /* XXX db->db_chrootDone, NULL */
71
72 /*@access rpmDiskSpaceInfo @*/
73 /*@access rpmKeyring @*/
74 /*@access rpmps @*/
75 /*@access rpmsx @*/
76 /*@access rpmte @*/
77 /*@access rpmtsi @*/
78 /*@access fnpyKey @*/
79 /*@access pgpDig @*/
80 /*@access pgpDigParams @*/
81
82 /*@unchecked@*/
83 int _rpmts_debug = 0;
84
85 /*@unchecked@*/
86 int _rpmts_stats = 0;
87
88 /*@unchecked@*/
89 int _rpmts_macros = 0;
90
91 int rpmtsCloseDB(rpmts ts)
92 {
93 int rc = 0;
94
95 if (ts->rdb != NULL) {
96 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->rdb->db_getops);
97 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->rdb->db_putops);
98 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->rdb->db_delops);
99 rc = rpmdbClose(ts->rdb);
100 ts->rdb = NULL;
101 }
102 return rc;
103 }
104
105 int rpmtsOpenDB(rpmts ts, int dbmode)
106 {
107 int rc = 0;
108
109 if (ts->rdb != NULL && ts->dbmode == dbmode)
110 return 0;
111
112 (void) rpmtsCloseDB(ts);
113
114 /* XXX there's a db lock race here that is the callers responsibility. */
115
116 ts->dbmode = dbmode;
117 rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
118 if (rc) {
119 const char * dn;
120 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
121 rpmlog(RPMLOG_ERR,
122 _("cannot open Packages database in %s\n"), dn);
123 dn = _free(dn);
124 }
125 return rc;
126 }
127
128 int rpmtsInitDB(rpmts ts, int dbmode)
129 {
130 #if defined(SUPPORT_INITDB)
131 void *lock = rpmtsAcquireLock(ts);
132 int rc = rpmdbInit(ts->rootDir, dbmode);
133 lock = rpmtsFreeLock(lock);
134 return rc;
135 #else
136 return -1;
137 #endif
138 }
139
140 int rpmtsRebuildDB(rpmts ts)
141 {
142 void * lock = rpmtsAcquireLock(ts);
143 int rc = rpmtsOpenDB(ts, ts->dbmode);
144
145 if (rc == 0)
146 rc = rpmdbRebuild(ts->rootDir,
147 (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK) ? ts : NULL));
148 lock = rpmtsFreeLock(lock);
149 return rc;
150 }
151
152 int rpmtsVerifyDB(rpmts ts)
153 {
154 #if defined(SUPPORT_VERIFYDB)
155 return rpmdbVerify(ts->rootDir);
156 #else
157 return -1;
158 #endif
159 }
160
161 /*@-compdef@*/ /* keyp might not be defined. */
162 rpmmi rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
163 const void * keyp, size_t keylen)
164 {
165 rpmmi mi;
166 const char * arch = NULL;
167 int xx;
168
169 if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
170 return NULL;
171
172 /* Parse out "N(EVR).A" tokens from a label key. */
173 if (rpmtag == RPMDBI_LABEL && keyp != NULL) {
174 const char * s = keyp;
175 const char *se;
176 size_t slen = strlen(s);
177 char *t = alloca(slen+1);
178 int level = 0;
179 int c;
180
181 keyp = t;
182 while ((c = *s++) != '\0') {
183 switch (c) {
184 default:
185 *t++ = (char)c;
186 /*@switchbreak@*/ break;
187 case '(':
188 /* XXX Fail if nested parens. */
189 if (level++ != 0) {
190 rpmlog(RPMLOG_ERR, _("extra '(' in package label: %s\n"), (char *)keyp);
191 return NULL;
192 }
193 /* Parse explicit epoch. */
194 for (se = s; *se && xisdigit(*se); se++)
195 {};
196 if (*se == ':') {
197 /* XXX skip explicit epoch's (for now) */
198 *t++ = '-';
199 s = se + 1;
200 } else {
201 /* No Epoch: found. Convert '(' to '-' and chug. */
202 *t++ = '-';
203 }
204 /*@switchbreak@*/ break;
205 case ')':
206 /* XXX Fail if nested parens. */
207 if (--level != 0) {
208 rpmlog(RPMLOG_ERR, _("missing '(' in package label: %s\n"), (char *)keyp);
209 return NULL;
210 }
211 /* Don't copy trailing ')' */
212 /*@switchbreak@*/ break;
213 }
214 }
215 if (level) {
216 rpmlog(RPMLOG_ERR, _("missing ')' in package label: %s\n"), (char *)keyp);
217 return NULL;
218 }
219 *t = '\0';
220 t = (char *) keyp;
221 t = strrchr(t, '.');
222 /* Is this a valid ".arch" suffix? */
223 if (t != NULL && rpmnsArch(t+1)) {
224 *t++ = '\0';
225 arch = t;
226 }
227 }
228
229 mi = rpmmiInit(ts->rdb, rpmtag, keyp, keylen);
230
231 /* Verify header signature/digest during retrieve (if not disabled). */
232 if (mi && !(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
233 (void) rpmmiSetHdrChk(mi, ts);
234
235 /* Select specified arch only. */
236 if (arch != NULL)
237 xx = rpmmiAddPattern(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch);
238 return mi;
239 }
240 /*@=compdef@*/
241
242 int rpmtsCloseSDB(rpmts ts)
243 {
244 int rc = 0;
245
246 if (ts->sdb != NULL) {
247 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->sdb->db_getops);
248 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->sdb->db_putops);
249 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->sdb->db_delops);
250 rc = rpmdbClose(ts->sdb);
251 ts->sdb = NULL;
252 }
253 return rc;
254 }
255
256 int rpmtsOpenSDB(rpmts ts, int dbmode)
257 {
258 static int has_sdbpath = -1;
259 int rc = 0;
260
261 if (ts->sdb != NULL && ts->sdbmode == dbmode)
262 return 0;
263
264 if (has_sdbpath < 0)
265 has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}");
266
267 /* If not configured, don't try to open. */
268 if (has_sdbpath <= 0)
269 return 1;
270
271 addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT);
272
273 rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644);
274 if (rc) {
275 const char * dn;
276 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
277 rpmlog(RPMLOG_WARNING,
278 _("cannot open Solve database in %s\n"), dn);
279 dn = _free(dn);
280 /* XXX only try to open the solvedb once. */
281 has_sdbpath = 0;
282 }
283 delMacro(NULL, "_dbpath");
284
285 return rc;
286 }
287
294 static int sugcmp(const void * a, const void * b)
295 /*@*/
296 {
297 const char * astr = *(const char **)a;
298 const char * bstr = *(const char **)b;
299 return strcmp(astr, bstr);
300 }
301
302 int rpmtsSolve(rpmts ts, rpmds ds, /*@unused@*/ const void * data)
303 {
304 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
305 const char * errstr;
306 const char * str = NULL;
307 const char * qfmt;
308 rpmmi mi;
309 Header bh = NULL;
310 Header h = NULL;
311 size_t bhnamelen = 0;
312 time_t bhtime = 0;
313 rpmTag rpmtag;
314 const char * keyp;
315 size_t keylen = 0;
316 int rc = 1; /* assume not found */
317 int xx;
318
319 /* Make suggestions only for installing Requires: */
320 if (ts->goal != TSM_INSTALL)
321 return rc;
322
323 switch (rpmdsTagN(ds)) {
324 case RPMTAG_CONFLICTNAME:
325 default:
326 return rc;
327 /*@notreached@*/ break;
328 case RPMTAG_DIRNAMES: /* XXX perhaps too many wrong answers */
329 case RPMTAG_REQUIRENAME:
330 case RPMTAG_FILELINKTOS:
331 break;
332 }
333
334 keyp = rpmdsN(ds);
335 if (keyp == NULL)
336 return rc;
337
338 if (ts->sdb == NULL) {
339 xx = rpmtsOpenSDB(ts, ts->sdbmode);
340 if (xx) return rc;
341 }
342
343 /* Look for a matching Provides: in suggested universe. */
344 rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME);
345 mi = rpmmiInit(ts->sdb, rpmtag, keyp, keylen);
346 while ((h = rpmmiNext(mi)) != NULL) {
347 size_t hnamelen;
348 time_t htime;
349
350 if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1))
351 continue;
352
353 he->tag = RPMTAG_NAME;
354 xx = headerGet(h, he, 0);
355 hnamelen = ((xx && he->p.str) ? strlen(he->p.str) : 0);
356 he->p.ptr = _free(he->p.ptr);
357
358 /* XXX Prefer the shortest pkg N for basenames/provides resp. */
359 if (bhnamelen > 0 && hnamelen > bhnamelen)
360 continue;
361
362 /* XXX Prefer the newest build if given alternatives. */
363 he->tag = RPMTAG_BUILDTIME;
364 xx = headerGet(h, he, 0);
365 htime = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
366 he->p.ptr = _free(he->p.ptr);
367
368 if (htime <= bhtime)
369 continue;
370
371 /* Save new "best" candidate. */
372 (void)headerFree(bh);
373 bh = NULL;
374 bh = headerLink(h);
375 bhtime = htime;
376 bhnamelen = hnamelen;
377 }
378 mi = rpmmiFree(mi);
379
380 /* Is there a suggested resolution? */
381 if (bh == NULL)
382 goto exit;
383
384 /* Format the suggested resolution path. */
385 qfmt = rpmExpand("%{?_solve_name_fmt}", NULL);
386 if (qfmt == NULL || *qfmt == '\0')
387 goto exit;
388 str = headerSprintf(bh, qfmt, NULL, rpmHeaderFormats, &errstr);
389 (void)headerFree(bh);
390 bh = NULL;
391 qfmt = _free(qfmt);
392 if (str == NULL) {
393 rpmlog(RPMLOG_ERR, _("incorrect solve path format: %s\n"), errstr);
394 goto exit;
395 }
396
397 if (ts->depFlags & RPMDEPS_FLAG_ADDINDEPS) {
398 FD_t fd;
399 rpmRC rpmrc;
400
401 fd = Fopen(str, "r.fdio");
402 if (fd == NULL || Ferror(fd)) {
403 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), str,
404 Fstrerror(fd));
405 if (fd != NULL) {
406 xx = Fclose(fd);
407 fd = NULL;
408 }
409 str = _free(str);
410 goto exit;
411 }
412 rpmrc = rpmReadPackageFile(ts, fd, str, &h);
413 xx = Fclose(fd);
414 switch (rpmrc) {
415 default:
416 break;
417 case RPMRC_NOTTRUSTED:
418 case RPMRC_NOKEY:
419 case RPMRC_OK:
420 if (h != NULL &&
421 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL))
422 {
423 rpmlog(RPMLOG_DEBUG, D_("Adding: %s\n"), str);
424 rc = -1; /* XXX restart unsatisfiedDepends() */
425 break;
426 }
427 break;
428 }
429 str = _free(str);
430 (void)headerFree(h);
431 h = NULL;
432 goto exit;
433 }
434
435 rpmlog(RPMLOG_DEBUG, D_("Suggesting: %s\n"), str);
436 /* If suggestion is already present, don't bother. */
437 if (ts->suggests != NULL && ts->nsuggests > 0) {
438 if (bsearch(&str, ts->suggests, ts->nsuggests,
439 sizeof(*ts->suggests), sugcmp))
440 {
441 str = _free(str);
442 goto exit;
443 }
444 }
445
446 /* Add a new (unique) suggestion. */
447 ts->suggests = xrealloc(ts->suggests,
448 sizeof(*ts->suggests) * (ts->nsuggests + 2));
449 ts->suggests[ts->nsuggests] = str;
450 ts->nsuggests++;
451 ts->suggests[ts->nsuggests] = NULL;
452
453 if (ts->nsuggests > 1)
454 qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp);
455
456 exit:
457 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
458 return rc;
459 /*@=nullstate@*/
460 }
461
462 int rpmtsAvailable(rpmts ts, const rpmds ds)
463 {
464 fnpyKey * sugkey;
465 int rc = 1; /* assume not found */
466
467 if (ts->availablePackages == NULL)
468 return rc;
469 sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL);
470 if (sugkey == NULL)
471 return rc;
472
473 /* XXX no alternatives yet */
474 if (sugkey[0] != NULL) {
475 ts->suggests = xrealloc(ts->suggests,
476 sizeof(*ts->suggests) * (ts->nsuggests + 2));
477 ts->suggests[ts->nsuggests] = sugkey[0];
478 sugkey[0] = NULL;
479 ts->nsuggests++;
480 ts->suggests[ts->nsuggests] = NULL;
481 }
482 sugkey = _free(sugkey);
483 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
484 return rc;
485 /*@=nullstate@*/
486 }
487
488 int rpmtsSetSolveCallback(rpmts ts,
489 int (*solve) (rpmts ts, rpmds key, const void * data),
490 const void * solveData)
491 {
492 int rc = 0;
493
494 if (ts) {
495 /*@-assignexpose -temptrans @*/
496 ts->solve = solve;
497 ts->solveData = solveData;
498 /*@=assignexpose =temptrans @*/
499 }
500 return rc;
501 }
502
503 rpmps rpmtsProblems(rpmts ts)
504 {
505 static const char msg[] = "rpmtsProblems";
506 rpmps ps = NULL;
507 if (ts) {
508 if (ts->probs == NULL)
509 ts->probs = rpmpsCreate();
510 /*@-castexpose@*/
511 ps = rpmpsLink(ts->probs, msg);
512 /*@=castexpose@*/
513 }
514 return ps;
515 }
516
517 void rpmtsClean(rpmts ts)
518 {
519 rpmtsi pi; rpmte p;
520
521 if (ts == NULL)
522 return;
523
524 /* Clean up after dependency checks. */
525 pi = rpmtsiInit(ts);
526 while ((p = rpmtsiNext(pi, 0)) != NULL)
527 rpmteCleanDS(p);
528 pi = rpmtsiFree(pi);
529
530 ts->addedPackages = rpmalFree(ts->addedPackages);
531 ts->numAddedPackages = 0;
532
533 ts->erasedPackages = rpmalFree(ts->erasedPackages);
534 ts->numErasedPackages = 0;
535
536 ts->suggests = _free(ts->suggests);
537 ts->nsuggests = 0;
538
539 ts->probs = rpmpsFree(ts->probs);
540
541 rpmtsCleanDig(ts);
542 }
543
544 void rpmtsEmpty(rpmts ts)
545 {
546 rpmtsi pi; rpmte p;
547 int oc;
548
549 if (ts == NULL)
550 return;
551
552 /*@-nullstate@*/ /* FIX: partial annotations */
553 rpmtsClean(ts);
554 /*@=nullstate@*/
555
556 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
557 /*@-type -unqualifiedtrans @*/
558 ts->order[oc] = rpmteFree(ts->order[oc]);
559 /*@=type =unqualifiedtrans @*/
560 }
561 pi = rpmtsiFree(pi);
562
563 ts->orderCount = 0;
564 ts->ntrees = 0;
565 ts->maxDepth = 0;
566
567 ts->numRemovedPackages = 0;
568 /*@-nullstate@*/ /* FIX: partial annotations */
569 return;
570 /*@=nullstate@*/
571 }
572
573 static void rpmtsPrintStat(const char * name, /*@null@*/ struct rpmop_s * op)
574 /*@globals fileSystem @*/
575 /*@modifies fileSystem @*/
576 {
577 static unsigned int scale = (1000 * 1000);
578 if (op != NULL && op->count > 0)
579 fprintf(stderr, " %s %8d %6lu.%06lu MB %6lu.%06lu secs\n",
580 name, op->count,
581 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
582 op->usecs/scale, op->usecs%scale);
583 }
584
585 /*@unchecked@*/ /*@relnull@*/
586 extern rpmop _hdr_loadops;
587 /*@unchecked@*/ /*@relnull@*/
588 extern rpmop _hdr_getops;
589
590 static void rpmtsPrintStats(rpmts ts)
591 /*@globals fileSystem, internalState @*/
592 /*@modifies fileSystem, internalState @*/
593 {
594 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
595
596 if (_hdr_loadops)
597 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRLOAD), _hdr_loadops);
598 if (_hdr_getops)
599 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRGET), _hdr_getops);
600
601 rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL));
602 rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK));
603 rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER));
604 rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
605 rpmtsPrintStat("repackage: ", rpmtsOp(ts, RPMTS_OP_REPACKAGE));
606 rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL));
607 rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE));
608 rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
609 rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
610 rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
611 rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST));
612 rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
613 rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD));
614 rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
615 rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET));
616 rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT));
617 rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL));
618 rpmtsPrintStat("readhdr: ", rpmtsOp(ts, RPMTS_OP_READHDR));
619 rpmtsPrintStat("hdrload: ", rpmtsOp(ts, RPMTS_OP_HDRLOAD));
620 rpmtsPrintStat("hdrget: ", rpmtsOp(ts, RPMTS_OP_HDRGET));
621 /*@-globstate@*/
622 return;
623 /*@=globstate@*/
624 }
625
626 static void rpmtsFini(void * _ts)
627 /*@modifies _ts @*/
628 {
629 rpmts ts = _ts;
630
631 /*@-nullstate@*/ /* FIX: partial annotations */
632 /* XXX there's a recursion here ... release and reacquire the lock */
633 #ifndef BUGGY
634 yarnRelease(ts->_item.use); /* XXX hack-o-round */
635 #endif
636 rpmtsEmpty(ts);
637 #ifndef BUGGY
638 yarnPossess(ts->_item.use); /* XXX hack-o-round */
639 #endif
640 /*@=nullstate@*/
641
642 ts->PRCO = rpmdsFreePRCO(ts->PRCO);
643
644 (void) rpmtsCloseDB(ts);
645
646 (void) rpmtsCloseSDB(ts);
647
648 ts->sx = rpmsxFree(ts->sx);
649
650 ts->removedPackages = _free(ts->removedPackages);
651
652 ts->availablePackages = rpmalFree(ts->availablePackages);
653 ts->numAvailablePackages = 0;
654
655 ts->dsi = _free(ts->dsi);
656
657 if (ts->scriptFd != NULL) {
658 /*@-refcounttrans@*/ /* FIX: XfdFree annotation */
659 ts->scriptFd = fdFree(ts->scriptFd, __FUNCTION__);
660 /*@=refcounttrans@*/
661 ts->scriptFd = NULL;
662 }
663 ts->rootDir = _free(ts->rootDir);
664 ts->currDir = _free(ts->currDir);
665
666 /*@-type +voidabstract @*/ /* FIX: double indirection */
667 ts->order = _free(ts->order);
668 /*@=type =voidabstract @*/
669 ts->orderAlloced = 0;
670
671 ts->keyring = rpmKeyringFree(ts->keyring);
672 ts->pkpkt = _free(ts->pkpkt);
673 ts->pkpktlen = 0;
674 memset(ts->pksignid, 0, sizeof(ts->pksignid));
675
676 if (_rpmts_stats)
677 rpmtsPrintStats(ts);
678
679 if (_rpmts_macros) {
680 const char ** av = NULL;
681 /*@-globs@*/ /* Avoid rpmGlobalMcroContext et al. */
682 (void)rpmGetMacroEntries(NULL, NULL, 1, &av);
683 /*@=globs@*/
684 argvPrint("macros used", av, NULL);
685 av = argvFree(av);
686 }
687 }
688
689 /*@unchecked@*/ /*@only@*/ /*@null@*/
690 rpmioPool _rpmtsPool;
691
692 static rpmts rpmtsGetPool(/*@null@*/ rpmioPool pool)
693 /*@globals _rpmtsPool, fileSystem, internalState @*/
694 /*@modifies pool, _rpmtsPool, fileSystem, internalState @*/
695 {
696 rpmts ts;
697
698 if (_rpmtsPool == NULL) {
699 _rpmtsPool = rpmioNewPool("ts", sizeof(*ts), -1, _rpmts_debug,
700 NULL, NULL, rpmtsFini);
701 pool = _rpmtsPool;
702 }
703 return (rpmts) rpmioGetPool(pool, sizeof(*ts));
704 }
705
706 void * rpmtsGetKeyring(rpmts ts, /*@unused@*/ int autoload)
707 {
708 rpmKeyring keyring = NULL;
709 if (ts) {
710 #ifdef NOTYET
711 if (ts->keyring == NULL && autoload)
712 loadKeyring(ts);
713 keyring = rpmKeyringLink(ts->keyring);
714 #else
715 keyring = ts->keyring;
716 #endif
717 }
718 /*@-refcounttrans@*/
719 return (void *)keyring;
720 /*@=refcounttrans@*/
721 }
722
723 int rpmtsSetKeyring(rpmts ts, void * _keyring)
724 {
725 rpmKeyring keyring = _keyring;
726
727 if (ts == NULL)
728 return -1;
729
730 #ifdef NOTYET
731 /*
732 * Should we permit switching keyring on the fly? For now, require
733 * rpmdb isn't open yet (fairly arbitrary limitation)...
734 */
735 if (rpmtsGetRdb(ts) != NULL)
736 return -1;
737 #endif
738
739 /*@-modnomods@*/
740 ts->keyring = rpmKeyringFree(ts->keyring);
741 /*@=modnomods@*/
742
743 #ifdef NOTYET
744 ts->keyring = rpmKeyringLink(keyring);
745 #else
746 /*@-assignexpose -newreftrans @*/
747 /*@i@*/ ts->keyring = keyring;
748 /*@=assignexpose =newreftrans @*/
749 #endif
750
751 return 0;
752 }
753
754 rpmVSFlags rpmtsVSFlags(/*@unused@*/ rpmts ts)
755 {
756 return pgpDigVSFlags;
757 }
758
759 rpmVSFlags rpmtsSetVSFlags(/*@unused@*/ rpmts ts, rpmVSFlags vsflags)
760 /*@globals pgpDigVSFlags @*/
761 /*@modifies pgpDigVSFlags @*/
762 {
763 rpmVSFlags ovsflags;
764 ovsflags = pgpDigVSFlags;
765 pgpDigVSFlags = vsflags;
766 return ovsflags;
767 }
768
769 /*
770 * This allows us to mark transactions as being of a certain type.
771 * The three types are:
772 *
773 * RPM_TRANS_NORMAL
774 * RPM_TRANS_ROLLBACK
775 * RPM_TRANS_AUTOROLLBACK
776 *
777 * ROLLBACK and AUTOROLLBACK transactions should always be ran as
778 * a best effort. In particular this is important to the autorollback
779 * feature to avoid rolling back a rollback (otherwise known as
780 * dueling rollbacks (-;). AUTOROLLBACK's additionally need instance
781 * counts passed to scriptlets to be altered.
782 */
783 /* Let them know what type of transaction we are */
784 rpmTSType rpmtsType(rpmts ts)
785 {
786 return ((ts != NULL) ? ts->type : 0);
787 }
788
789 void rpmtsSetType(rpmts ts, rpmTSType type)
790 {
791 if (ts != NULL)
792 ts->type = type;
793 }
794
795 rpmuint32_t rpmtsARBGoal(rpmts ts)
796 {
797 return ((ts != NULL) ? ts->arbgoal : 0);
798 }
799
800 void rpmtsSetARBGoal(rpmts ts, rpmuint32_t goal)
801 {
802 if (ts != NULL)
803 ts->arbgoal = goal;
804 }
805
806 int rpmtsUnorderedSuccessors(rpmts ts, int first)
807 {
808 int unorderedSuccessors = 0;
809 if (ts != NULL) {
810 unorderedSuccessors = ts->unorderedSuccessors;
811 if (first >= 0)
812 ts->unorderedSuccessors = first;
813 }
814 return unorderedSuccessors;
815 }
816
817 const char * rpmtsRootDir(rpmts ts)
818 {
819 const char * rootDir = NULL;
820
821 if (ts != NULL && ts->rootDir != NULL) {
822 urltype ut = urlPath(ts->rootDir, &rootDir);
823 switch (ut) {
824 case URL_IS_UNKNOWN:
825 case URL_IS_PATH:
826 break;
827 case URL_IS_HTTPS:
828 case URL_IS_HTTP:
829 case URL_IS_HKP:
830 case URL_IS_FTP:
831 case URL_IS_DASH:
832 default:
833 rootDir = "/";
834 break;
835 }
836 }
837 return rootDir;
838 }
839
840 void rpmtsSetRootDir(rpmts ts, const char * rootDir)
841 {
842 if (ts != NULL) {
843 size_t rootLen;
844
845 ts->rootDir = _free(ts->rootDir);
846
847 if (rootDir == NULL) {
848 #ifndef DYING
849 ts->rootDir = xstrdup("");
850 #endif
851 return;
852 }
853 rootLen = strlen(rootDir);
854
855 /* Make sure that rootDir has trailing / */
856 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
857 char * t = alloca(rootLen + 2);
858 *t = '\0';
859 (void) stpcpy( stpcpy(t, rootDir), "/");
860 rootDir = t;
861 }
862 ts->rootDir = xstrdup(rootDir);
863 }
864 }
865
866 const char * rpmtsCurrDir(rpmts ts)
867 {
868 const char * currDir = NULL;
869 if (ts != NULL) {
870 currDir = ts->currDir;
871 }
872 return currDir;
873 }
874
875 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
876 {
877 if (ts != NULL) {
878 ts->currDir = _free(ts->currDir);
879 if (currDir)
880 ts->currDir = xstrdup(currDir);
881 }
882 }
883
884 FD_t rpmtsScriptFd(rpmts ts)
885 {
886 FD_t scriptFd = NULL;
887 if (ts != NULL) {
888 scriptFd = ts->scriptFd;
889 }
890 /*@-compdef -refcounttrans -usereleased@*/
891 return scriptFd;
892 /*@=compdef =refcounttrans =usereleased@*/
893 }
894
895 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
896 {
897
898 if (ts != NULL) {
899 if (ts->scriptFd != NULL) {
900 /*@-assignexpose@*/
901 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd");
902 /*@=assignexpose@*/
903 ts->scriptFd = NULL;
904 }
905 /*@-assignexpose -castexpose @*/
906 if (scriptFd != NULL)
907 ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd");
908 /*@=assignexpose =castexpose @*/
909 }
910 }
911
912 int rpmtsSELinuxEnabled(rpmts ts)
913 {
914 int selinuxEnabled = 0;
915 if (ts)
916 selinuxEnabled = (ts->selinuxEnabled > 0);
917 return selinuxEnabled;
918 }
919
920 int rpmtsChrootDone(rpmts ts)
921 {
922 return (ts != NULL ? ts->chrootDone : 0);
923 }
924
925 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
926 {
927 int ochrootDone = 0;
928 if (ts != NULL) {
929 ochrootDone = ts->chrootDone;
930 if (ts->rdb != NULL)
931 ts->rdb->db_chrootDone = chrootDone;
932 ts->chrootDone = chrootDone;
933 }
934 return ochrootDone;
935 }
936
937 rpmuint32_t rpmtsGetTid(rpmts ts)
938 {
939 rpmuint32_t tid = 0; /* XXX -1 is time(2) error return. */
940 if (ts != NULL) {
941 tid = ts->tid[0];
942 }
943 return tid;
944 }
945
946 rpmuint32_t rpmtsSetTid(rpmts ts, rpmuint32_t tid)
947 {
948 rpmuint32_t otid = 0; /* XXX -1 is time(2) error return. */
949 if (ts != NULL) {
950 otid = ts->tid[0];
951 ts->tid[0] = tid;
952 ts->tid[1] = 0;
953 }
954 return otid;
955 }
956
957 rpmPRCO rpmtsPRCO(rpmts ts)
958 {
959 rpmPRCO PRCO = NULL;
960
961 if (ts != NULL) {
962 static int oneshot = 0;
963 if (!oneshot) {
964 const char * fn = rpmGetPath("%{?_rpmds_sysinfo_path}", NULL);
965 int xx;
966
967 ts->PRCO = rpmdsNewPRCO(NULL);
968 if (fn && *fn != '\0' && !rpmioAccess(fn, NULL, R_OK))
969 xx = rpmdsSysinfo(ts->PRCO, NULL);
970 fn = _free(fn);
971 oneshot++;
972 }
973 PRCO = ts->PRCO;
974 }
975 /*@-compdef -retexpose -usereleased @*/
976 return PRCO;
977 /*@=compdef =retexpose =usereleased @*/
978 }
979
980 int rpmtsInitDSI(const rpmts ts)
981 {
982 rpmDiskSpaceInfo dsi;
983 struct stat sb;
984 int rc;
985 size_t i;
986
987 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
988 return 0;
989 if (ts->filesystems != NULL)
990 return 0;
991
992 rpmlog(RPMLOG_DEBUG, D_("mounted filesystems:\n"));
993 rpmlog(RPMLOG_DEBUG,
994 D_(" i dev bsize bavail iavail mount point\n"));
995
996 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
997 if (rc || ts->filesystems == NULL || ts->filesystemCount == 0)
998 return rc;
999
1000 /* Get available space on mounted file systems. */
1001
1002 ts->dsi = _free(ts->dsi);
1003 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
1004
1005 dsi = ts->dsi;
1006
1007 if (dsi != NULL)
1008 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
1009 #if STATFS_IN_SYS_STATVFS
1010 struct statvfs sfb;
1011 memset(&sfb, 0, sizeof(sfb));
1012 rc = statvfs(ts->filesystems[i], &sfb);
1013 #else
1014 struct statfs sfb;
1015 memset(&sfb, 0, sizeof(sfb));
1016 # if STAT_STATFS4
1017 /* This platform has the 4-argument version of the statfs call. The last two
1018 * should be the size of struct statfs and 0, respectively. The 0 is the
1019 * filesystem type, and is always 0 when statfs is called on a mounted
1020 * filesystem, as we're doing.
1021 */
1022 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
1023 # else
1024 rc = statfs(ts->filesystems[i], &sfb);
1025 # endif
1026 #endif
1027 if (rc)
1028 break;
1029
1030 rc = stat(ts->filesystems[i], &sb);
1031 if (rc)
1032 break;
1033 dsi->dev = sb.st_dev;
1034 /* XXX figger out how to get this info for non-statvfs systems. */
1035 #if STATFS_IN_SYS_STATVFS
1036 dsi->f_frsize = sfb.f_frsize;
1037 #if defined(RPM_OS_AIX)
1038 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on AIX */
1039 #else
1040 dsi->f_fsid = sfb.f_fsid;
1041 #endif
1042 dsi->f_flag = sfb.f_flag;
1043 dsi->f_favail = (long long) sfb.f_favail;
1044 dsi->f_namemax = sfb.f_namemax;
1045 #elif defined(__APPLE__) && defined(__MACH__) && !defined(_SYS_STATVFS_H_)
1046 dsi->f_fsid = 0; /* "Not meaningful in this implementation." */
1047 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX);
1048 #elif defined(__OpenBSD__)
1049 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on OpenBSD */
1050 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX);
1051 #else
1052 dsi->f_fsid = sfb.f_fsid;
1053 dsi->f_namemax = sfb.f_namelen;
1054 #endif
1055
1056 dsi->f_bsize = sfb.f_bsize;
1057 dsi->f_blocks = (unsigned long long)sfb.f_blocks;
1058 dsi->f_bfree = (unsigned long long)sfb.f_bfree;
1059 dsi->f_files = (unsigned long long)sfb.f_files;
1060 dsi->f_ffree = (unsigned long long)sfb.f_ffree;
1061
1062 dsi->bneeded = 0;
1063 dsi->ineeded = 0;
1064 #ifdef STATFS_HAS_F_BAVAIL
1065 dsi->f_bavail = (long long)(sfb.f_bavail ? sfb.f_bavail : 1);
1066 if (sfb.f_ffree > 0 && sfb.f_files > 0 && sfb.f_favail > 0)
1067 dsi->f_favail = (long long)sfb.f_favail;
1068 else /* XXX who knows what evil lurks here? */
1069 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
1070 ? (signed long long) sfb.f_ffree : -1;
1071 #else
1072 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
1073 * available for non-superusers. f_blocks - f_bfree is probably too big, but
1074 * it's about all we can do.
1075 */
1076 dsi->f_bavail = sfb.f_blocks - sfb.f_bfree;
1077 /* XXX Avoid FAT and other file systems that have not inodes. */
1078 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
1079 ? sfb.f_ffree : -1;
1080 #endif
1081
1082 #if !defined(ST_RDONLY)
1083 #define ST_RDONLY 1
1084 #endif
1085 rpmlog(RPMLOG_DEBUG, "%5u 0x%08x %8u %12ld %12ld %s %s\n",
1086 (unsigned)i, (unsigned) dsi->dev, (unsigned) dsi->f_bsize,
1087 (signed long) dsi->f_bavail, (signed long) dsi->f_favail,
1088 ((dsi->f_flag & ST_RDONLY) ? "ro" : "rw"),
1089 ts->filesystems[i]);
1090 }
1091 return rc;
1092 }
1093
1094 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
1095 rpmuint32_t fileSize, rpmuint32_t prevSize, rpmuint32_t fixupSize,
1096 int _action)
1097 {
1098 iosmFileAction action = _action;
1099 rpmDiskSpaceInfo dsi;
1100 rpmuint64_t bneeded;
1101
1102 dsi = ts->dsi;
1103 if (dsi) {
1104 while (dsi->f_bsize && dsi->dev != dev)
1105 dsi++;
1106 if (dsi->f_bsize == 0)
1107 dsi = NULL;
1108 }
1109 if (dsi == NULL)
1110 return;
1111
1112 bneeded = BLOCK_ROUND(fileSize, dsi->f_bsize);
1113
1114 switch (action) {
1115 case FA_BACKUP:
1116 case FA_SAVE:
1117 case FA_ALTNAME:
1118 dsi->ineeded++;
1119 dsi->bneeded += bneeded;
1120 /*@switchbreak@*/ break;
1121
1122 /*
1123 * FIXME: If two packages share a file (same md5sum), and
1124 * that file is being replaced on disk, will dsi->bneeded get
1125 * adjusted twice? Quite probably!
1126 */
1127 case FA_CREATE:
1128 dsi->bneeded += bneeded;
1129 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->f_bsize);
1130 /*@switchbreak@*/ break;
1131
1132 case FA_ERASE:
1133 dsi->ineeded--;
1134 dsi->bneeded -= bneeded;
1135 /*@switchbreak@*/ break;
1136
1137 default:
1138 /*@switchbreak@*/ break;
1139 }
1140
1141 if (fixupSize)
1142 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->f_bsize);
1143 }
1144
1145 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
1146 {
1147 rpmDiskSpaceInfo dsi;
1148 rpmps ps;
1149 int fc;
1150 size_t i;
1151
1152 if (ts->filesystems == NULL || ts->filesystemCount == 0)
1153 return;
1154
1155 dsi = ts->dsi;
1156 if (dsi == NULL)
1157 return;
1158 fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) );
1159 if (fc <= 0)
1160 return;
1161
1162 ps = rpmtsProblems(ts);
1163 for (i = 0; i < ts->filesystemCount; i++, dsi++) {
1164
1165 if (dsi->f_bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->f_bavail) {
1166 rpmpsAppend(ps, RPMPROB_DISKSPACE,
1167 rpmteNEVR(te), rpmteKey(te),
1168 ts->filesystems[i], NULL, NULL,
1169 (adj_fs_blocks(dsi->bneeded) - dsi->f_bavail) * dsi->f_bsize);
1170 }
1171
1172 if (dsi->f_favail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->f_favail) {
1173 rpmpsAppend(ps, RPMPROB_DISKNODES,
1174 rpmteNEVR(te), rpmteKey(te),
1175 ts->filesystems[i], NULL, NULL,
1176 (adj_fs_blocks(dsi->ineeded) - dsi->f_favail));
1177 }
1178
1179 if ((dsi->bneeded || dsi->ineeded) && (dsi->f_flag & ST_RDONLY)) {
1180 rpmpsAppend(ps, RPMPROB_RDONLY,
1181 rpmteNEVR(te), rpmteKey(te),
1182 ts->filesystems[i], NULL, NULL, 0);
1183 }
1184 }
1185 ps = rpmpsFree(ps);
1186 }
1187
1188 void * rpmtsNotify(rpmts ts, rpmte te,
1189 rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total)
1190 {
1191 void * ptr = NULL;
1192 if (ts && ts->notify) {
1193 Header h;
1194 fnpyKey cbkey;
1195 /*@-type@*/ /* FIX: cast? */
1196 /*@-noeffectuncon @*/ /* FIX: check rc */
1197 if (te) {
1198 /*@-castexpose -mods@*/ /* XXX noisy in transaction.c */
1199 h = headerLink(te->h);
1200 /*@=castexpose =mods@*/
1201 cbkey = rpmteKey(te);
1202 } else {
1203 h = NULL;
1204 cbkey = NULL;
1205 }
1206 ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData);
1207 (void)headerFree(h);
1208 h = NULL;
1209 /*@=noeffectuncon @*/
1210 /*@=type@*/
1211 }
1212 return ptr;
1213 }
1214
1215 int rpmtsNElements(rpmts ts)
1216 {
1217 int nelements = 0;
1218 if (ts != NULL && ts->order != NULL) {
1219 nelements = ts->orderCount;
1220 }
1221 return nelements;
1222 }
1223
1224 rpmte rpmtsElement(rpmts ts, int ix)
1225 {
1226 rpmte te = NULL;
1227 if (ts != NULL && ts->order != NULL) {
1228 if (ix >= 0 && ix < ts->orderCount)
1229 te = ts->order[ix];
1230 }
1231 /*@-compdef@*/
1232 return te;
1233 /*@=compdef@*/
1234 }
1235
1236 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
1237 {
1238 return (ts != NULL ? ts->ignoreSet : 0);
1239 }
1240
1241 rpmtransFlags rpmtsFlags(rpmts ts)
1242 {
1243 rpmtransFlags transFlags = 0;
1244 if (ts != NULL) {
1245 transFlags = ts->transFlags;
1246 if (rpmtsSELinuxEnabled(ts) > 0)
1247 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS;
1248 else
1249 transFlags |= RPMTRANS_FLAG_NOCONTEXTS;
1250 }
1251 return transFlags;
1252 }
1253
1254 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
1255 {
1256 rpmtransFlags otransFlags = 0;
1257 if (ts != NULL) {
1258 otransFlags = ts->transFlags;
1259 if (rpmtsSELinuxEnabled(ts) > 0)
1260 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS;
1261 else
1262 transFlags |= RPMTRANS_FLAG_NOCONTEXTS;
1263 ts->transFlags = transFlags;
1264 }
1265 return otransFlags;
1266 }
1267
1268 rpmdepFlags rpmtsDFlags(rpmts ts)
1269 {
1270 return (ts != NULL ? ts->depFlags : 0);
1271 }
1272
1273 rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags)
1274 {
1275 rpmdepFlags odepFlags = 0;
1276 if (ts != NULL) {
1277 odepFlags = ts->depFlags;
1278 ts->depFlags = depFlags;
1279 }
1280 return odepFlags;
1281 }
1282
1283 Spec rpmtsSpec(rpmts ts)
1284 {
1285 /*@-compdef -retexpose -usereleased@*/
1286 return ts->spec;
1287 /*@=compdef =retexpose =usereleased@*/
1288 }
1289
1290 Spec rpmtsSetSpec(rpmts ts, Spec spec)
1291 {
1292 Spec ospec = ts->spec;
1293 /*@-assignexpose -temptrans@*/
1294 ts->spec = spec;
1295 /*@=assignexpose =temptrans@*/
1296 return ospec;
1297 }
1298
1299 rpmte rpmtsRelocateElement(rpmts ts)
1300 {
1301 /*@-compdef -retexpose -usereleased@*/
1302 return ts->relocateElement;
1303 /*@=compdef =retexpose =usereleased@*/
1304 }
1305
1306 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement)
1307 {
1308 rpmte orelocateElement = ts->relocateElement;
1309 /*@-assignexpose -temptrans@*/
1310 ts->relocateElement = relocateElement;
1311 /*@=assignexpose =temptrans@*/
1312 return orelocateElement;
1313 }
1314
1315 tsmStage rpmtsGoal(rpmts ts)
1316 {
1317 return (ts != NULL ? ts->goal : TSM_UNKNOWN);
1318 }
1319
1320 tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal)
1321 {
1322 tsmStage ogoal = TSM_UNKNOWN;
1323 if (ts != NULL) {
1324 ogoal = ts->goal;
1325 ts->goal = goal;
1326 }
1327 return ogoal;
1328 }
1329
1330 int rpmtsDBMode(rpmts ts)
1331 {
1332 return (ts != NULL ? ts->dbmode : 0);
1333 }
1334
1335 int rpmtsSetDBMode(rpmts ts, int dbmode)
1336 {
1337 int odbmode = 0;
1338 if (ts != NULL) {
1339 odbmode = ts->dbmode;
1340 ts->dbmode = dbmode;
1341 }
1342 return odbmode;
1343 }
1344
1345 rpmuint32_t rpmtsColor(rpmts ts)
1346 {
1347 return (ts != NULL ? ts->color : 0);
1348 }
1349
1350 rpmuint32_t rpmtsSetColor(rpmts ts, rpmuint32_t color)
1351 {
1352 rpmuint32_t ocolor = 0;
1353 if (ts != NULL) {
1354 ocolor = ts->color;
1355 ts->color = color;
1356 }
1357 return ocolor;
1358 }
1359
1360 rpmuint32_t rpmtsPrefColor(rpmts ts)
1361 {
1362 return (ts != NULL ? ts->prefcolor : 0);
1363 }
1364
1365 int rpmtsSetNotifyCallback(rpmts ts,
1366 rpmCallbackFunction notify, rpmCallbackData notifyData)
1367 {
1368 if (ts != NULL) {
1369 ts->notify = notify;
1370 ts->notifyData = notifyData;
1371 }
1372 return 0;
1373 }
1374
1375 rpmts rpmtsCreate(void)
1376 {
1377 rpmts ts = rpmtsGetPool(_rpmtsPool);
1378 int xx;
1379
1380 memset(&ts->ops, 0, sizeof(ts->ops));
1381 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
1382 ts->type = RPMTRANS_TYPE_NORMAL;
1383 ts->goal = TSM_UNKNOWN;
1384 ts->filesystemCount = 0;
1385 ts->filesystems = NULL;
1386 ts->dsi = NULL;
1387
1388 ts->solve = rpmtsSolve;
1389 ts->solveData = NULL;
1390 ts->nsuggests = 0;
1391 ts->suggests = NULL;
1392
1393 ts->PRCO = NULL;
1394
1395 ts->sdb = NULL;
1396 ts->sdbmode = O_RDONLY;
1397
1398 ts->rdb = NULL;
1399 ts->dbmode = O_RDONLY;
1400
1401 ts->scriptFd = NULL;
1402 { struct timeval tv;
1403 xx = gettimeofday(&tv, NULL);
1404 ts->tid[0] = (rpmuint32_t) tv.tv_sec;
1405 ts->tid[1] = (rpmuint32_t) tv.tv_usec;
1406 }
1407 ts->delta = 5;
1408
1409 ts->color = rpmExpandNumeric("%{?_transaction_color}");
1410 ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}");
1411 if (!ts->prefcolor) ts->prefcolor = 0x2;
1412
1413 ts->numRemovedPackages = 0;
1414 ts->allocedRemovedPackages = ts->delta;
1415 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
1416 sizeof(*ts->removedPackages));
1417
1418 ts->rootDir = NULL;
1419 ts->currDir = NULL;
1420 ts->chrootDone = 0;
1421
1422 ts->selinuxEnabled = is_selinux_enabled();
1423
1424 ts->numAddedPackages = 0;
1425 ts->addedPackages = NULL;
1426
1427 ts->numErasedPackages = 0;
1428 ts->erasedPackages = NULL;
1429
1430 ts->numAvailablePackages = 0;
1431 ts->availablePackages = NULL;
1432
1433 ts->orderAlloced = 0;
1434 ts->orderCount = 0;
1435 ts->order = NULL;
1436 ts->ntrees = 0;
1437 ts->maxDepth = 0;
1438
1439 ts->probs = NULL;
1440
1441 ts->keyring = NULL;
1442 ts->pkpkt = NULL;
1443 ts->pkpktlen = 0;
1444 memset(ts->pksignid, 0, sizeof(ts->pksignid));
1445 ts->dig = NULL;
1446
1447 /* Set autorollback goal to the end of time. */
1448 ts->arbgoal = 0xffffffff;
1449
1450 return rpmtsLink(ts, "tsCreate");
1451 }