00001
00005 #include "system.h"
00006
00007 #include <rpmlib.h>
00008 #include <rpmte.h>
00009
00010 #define _RPMGI_INTERNAL
00011 #define _RPMTS_INTERNAL
00012 #include <rpmgi.h>
00013
00014 #include <rpmdb.h>
00015 #include <rpmmacro.h>
00016 #include "manifest.h"
00017
00018 #include "debug.h"
00019
00020
00021
00022
00023
00024
00025
00026 int _rpmgi_debug = 0;
00027
00028
00029 rpmgiFlags giFlags = RPMGI_NONE;
00030
00031
00032 static int indent = 2;
00033
00034
00035 static const char * ftsInfoStrings[] = {
00036 "UNKNOWN",
00037 "D",
00038 "DC",
00039 "DEFAULT",
00040 "DNR",
00041 "DOT",
00042 "DP",
00043 "ERR",
00044 "F",
00045 "INIT",
00046 "NS",
00047 "NSOK",
00048 "SL",
00049 "SLNONE",
00050 "W",
00051 };
00052
00053
00054 static const char * ftsInfoStr(int fts_info)
00055
00056 {
00057
00058 if (!(fts_info >= 1 && fts_info <= 14))
00059 fts_info = 0;
00060
00061 return ftsInfoStrings[ fts_info ];
00062
00063 }
00064
00072
00073 static FD_t rpmgiOpen(const char * path, const char * fmode)
00074
00075
00076 {
00077 const char * fn = rpmExpand(path, NULL);
00078 FD_t fd = Fopen(fn, fmode);
00079
00080 if (fd == NULL || Ferror(fd)) {
00081 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fn, Fstrerror(fd));
00082 if (fd != NULL) (void) Fclose(fd);
00083 fd = NULL;
00084 }
00085 fn = _free(fn);
00086
00087 return fd;
00088 }
00089
00096 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path)
00097
00098
00099 {
00100 FD_t fd = rpmgiOpen(path, "r.ufdio");
00101 rpmRC rpmrc = RPMRC_FAIL;
00102
00103 if (fd != NULL) {
00104 rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv);
00105 (void) Fclose(fd);
00106 }
00107 return rpmrc;
00108 }
00109
00116
00117 static Header rpmgiReadHeader(rpmgi gi, const char * path)
00118
00119
00120 {
00121 FD_t fd = rpmgiOpen(path, "r.ufdio");
00122 Header h = NULL;
00123
00124 if (fd != NULL) {
00125
00126 rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h);
00127
00128 (void) Fclose(fd);
00129
00130 switch (rpmrc) {
00131 case RPMRC_NOTFOUND:
00132
00133 case RPMRC_FAIL:
00134 default:
00135 h = headerFree(h);
00136 break;
00137 case RPMRC_NOTTRUSTED:
00138 case RPMRC_NOKEY:
00139 case RPMRC_OK:
00140 break;
00141 }
00142 }
00143
00144 return h;
00145 }
00146
00154
00155 static rpmRC rpmgiLoadReadHeader(rpmgi gi)
00156
00157
00158 {
00159 rpmRC rpmrc = RPMRC_NOTFOUND;
00160 Header h = NULL;
00161
00162 if (gi->argv != NULL && gi->argv[gi->i] != NULL)
00163 do {
00164 const char * fn;
00165
00166 fn = gi->argv[gi->i];
00167 if (!(gi->flags & RPMGI_NOHEADER)) {
00168 h = rpmgiReadHeader(gi, fn);
00169 if (h != NULL)
00170 rpmrc = RPMRC_OK;
00171 } else
00172 rpmrc = RPMRC_OK;
00173
00174 if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST)
00175 break;
00176 if (errno == ENOENT) {
00177 break;
00178 }
00179
00180
00181 gi->argv[gi->i] = NULL;
00182 rpmrc = rpmgiLoadManifest(gi, fn);
00183 if (rpmrc != RPMRC_OK) {
00184 gi->argv[gi->i] = fn;
00185 break;
00186 }
00187 fn = _free(fn);
00188 rpmrc = RPMRC_NOTFOUND;
00189 } while (1);
00190
00191 if (rpmrc == RPMRC_OK && h != NULL)
00192 gi->h = headerLink(h);
00193 h = headerFree(h);
00194
00195 return rpmrc;
00196 }
00197
00203
00204 static rpmRC rpmgiWalkPathFilter(rpmgi gi)
00205
00206 {
00207 FTSENT * fts = gi->fts;
00208 rpmRC rpmrc = RPMRC_NOTFOUND;
00209 const char * s;
00210
00211 if (_rpmgi_debug < 0)
00212 rpmMessage(RPMMESS_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info),
00213 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
00214 fts->fts_name,
00215 ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : ""));
00216
00217 switch (fts->fts_info) {
00218 case FTS_D:
00219 break;
00220 case FTS_DP:
00221 break;
00222 case FTS_F:
00223
00224 s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm");
00225 if (strcmp(s, ".rpm"))
00226 break;
00227 rpmrc = RPMRC_OK;
00228 break;
00229 case FTS_NS:
00230 case FTS_DNR:
00231 case FTS_ERR:
00232 break;
00233 case FTS_DC:
00234 case FTS_DEFAULT:
00235 case FTS_DOT:
00236 case FTS_INIT:
00237 case FTS_NSOK:
00238 case FTS_SL:
00239 case FTS_SLNONE:
00240 case FTS_W:
00241 default:
00242 break;
00243 }
00244 return rpmrc;
00245 }
00246
00252
00253 static rpmRC rpmgiWalkReadHeader(rpmgi gi)
00254
00255
00256 {
00257 rpmRC rpmrc = RPMRC_NOTFOUND;
00258
00259 if (gi->ftsp != NULL)
00260 while ((gi->fts = Fts_read(gi->ftsp)) != NULL) {
00261 rpmrc = rpmgiWalkPathFilter(gi);
00262 if (rpmrc == RPMRC_OK)
00263 break;
00264 }
00265
00266 if (rpmrc == RPMRC_OK) {
00267 Header h = NULL;
00268 if (!(gi->flags & RPMGI_NOHEADER)) {
00269
00270 if (gi->fts != NULL)
00271 h = rpmgiReadHeader(gi, gi->fts->fts_path);
00272 }
00273 if (h != NULL)
00274 gi->h = headerLink(h);
00275 h = headerFree(h);
00276 }
00277
00278 return rpmrc;
00279 }
00280
00287 static rpmRC rpmgiGlobArgv(rpmgi gi, ARGV_t argv)
00288
00289
00290 {
00291 const char * arg;
00292 rpmRC rpmrc = RPMRC_OK;
00293 int ac = 0;
00294 int xx;
00295
00296
00297 if ((gi->flags & RPMGI_NOGLOB)
00298 || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK))
00299 {
00300 if (argv != NULL) {
00301 while (argv[ac] != NULL)
00302 ac++;
00303
00304 xx = argvAppend(&gi->argv, argv);
00305
00306 }
00307 gi->argc = ac;
00308 return rpmrc;
00309 }
00310
00311 if (argv != NULL)
00312 while ((arg = *argv++) != NULL) {
00313 char * t = rpmEscapeSpaces(arg);
00314 ARGV_t av = NULL;
00315
00316 xx = rpmGlob(t, &ac, &av);
00317 xx = argvAppend(&gi->argv, av);
00318 gi->argc += ac;
00319 av = argvFree(av);
00320 t = _free(t);
00321 ac = 0;
00322 }
00323 return rpmrc;
00324 }
00325
00331 static rpmRC rpmgiInitFilter(rpmgi gi)
00332
00333
00334 {
00335 rpmRC rpmrc = RPMRC_OK;
00336 ARGV_t av;
00337 int res = 0;
00338
00339 gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen);
00340
00341 if (_rpmgi_debug < 0)
00342 fprintf(stderr, "*** gi %p\tmi %p\n", gi, gi->mi);
00343
00344 if (gi->argv != NULL)
00345 for (av = (const char **) gi->argv; *av != NULL; av++) {
00346 int tag = RPMTAG_NAME;
00347 const char * pat;
00348 char * a, * ae;
00349
00350 pat = a = xstrdup(*av);
00351 tag = RPMTAG_NAME;
00352
00353
00354
00355 if ((ae = strchr(a, '=')) != NULL) {
00356 *ae++ = '\0';
00357 tag = tagValue(a);
00358 if (tag < 0) {
00359 rpmError(RPMERR_QUERYINFO, _("unknown tag: \"%s\"\n"), a);
00360 res = 1;
00361 }
00362 pat = ae;
00363 }
00364
00365
00366 if (!res) {
00367 if (_rpmgi_debug < 0)
00368 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (av - gi->argv), *av, tagName(tag), pat);
00369 res = rpmdbSetIteratorRE(gi->mi, tag, RPMMIRE_DEFAULT, pat);
00370 }
00371 a = _free(a);
00372
00373 if (res == 0)
00374 continue;
00375
00376 gi->mi = rpmdbFreeIterator(gi->mi);
00377 rpmrc = RPMRC_FAIL;
00378 break;
00379 }
00380
00381 return rpmrc;
00382 }
00383
00384 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00385 {
00386 if (gi == NULL) return NULL;
00387
00388 if (_rpmgi_debug && msg != NULL)
00389 fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00390
00391 gi->nrefs--;
00392 return NULL;
00393 }
00394
00395 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00396 {
00397 if (gi == NULL) return NULL;
00398 gi->nrefs++;
00399
00400 if (_rpmgi_debug && msg != NULL)
00401 fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00402
00403 return gi;
00404 }
00405
00406 rpmgi rpmgiFree(rpmgi gi)
00407 {
00408 if (gi == NULL)
00409 return NULL;
00410
00411 if (gi->nrefs > 1)
00412 return rpmgiUnlink(gi, __FUNCTION__);
00413
00414 (void) rpmgiUnlink(gi, __FUNCTION__);
00415
00416
00417
00418 gi->hdrPath = _free(gi->hdrPath);
00419 gi->h = headerFree(gi->h);
00420
00421 gi->argv = argvFree(gi->argv);
00422
00423 if (gi->ftsp != NULL) {
00424 int xx;
00425 xx = Fts_close(gi->ftsp);
00426 gi->ftsp = NULL;
00427 gi->fts = NULL;
00428 }
00429 if (gi->fd != NULL) {
00430 (void) Fclose(gi->fd);
00431 gi->fd = NULL;
00432 }
00433 gi->tsi = rpmtsiFree(gi->tsi);
00434 gi->mi = rpmdbFreeIterator(gi->mi);
00435 gi->ts = rpmtsFree(gi->ts);
00436
00437 memset(gi, 0, sizeof(*gi));
00438
00439 gi = _free(gi);
00440
00441
00442 return NULL;
00443 }
00444
00445 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
00446 {
00447 rpmgi gi = xcalloc(1, sizeof(*gi));
00448
00449 if (gi == NULL)
00450 return NULL;
00451
00452 gi->ts = rpmtsLink(ts, __FUNCTION__);
00453 gi->tag = tag;
00454
00455 gi->keyp = keyp;
00456
00457 gi->keylen = keylen;
00458
00459 gi->flags = 0;
00460 gi->active = 0;
00461 gi->i = -1;
00462 gi->errors = 0;
00463 gi->hdrPath = NULL;
00464 gi->h = NULL;
00465
00466 gi->tsi = NULL;
00467 gi->mi = NULL;
00468 gi->fd = NULL;
00469 gi->argv = xcalloc(1, sizeof(*gi->argv));
00470 gi->argc = 0;
00471 gi->ftsOpts = 0;
00472 gi->ftsp = NULL;
00473 gi->fts = NULL;
00474
00475 gi = rpmgiLink(gi, __FUNCTION__);
00476
00477 return gi;
00478 }
00479
00480 rpmRC rpmgiNext( rpmgi gi)
00481 {
00482 char hnum[32];
00483 rpmRC rpmrc = RPMRC_NOTFOUND;
00484 int xx;
00485
00486 if (gi == NULL)
00487 return rpmrc;
00488
00489
00490 gi->h = headerFree(gi->h);
00491 gi->hdrPath = _free(gi->hdrPath);
00492 hnum[0] = '\0';
00493
00494
00495 if (++gi->i >= 0)
00496 switch (gi->tag) {
00497 default:
00498 case RPMDBI_PACKAGES:
00499 if (!gi->active) {
00500 rpmrc = rpmgiInitFilter(gi);
00501 if (rpmrc != RPMRC_OK) {
00502 gi->mi = rpmdbFreeIterator(gi->mi);
00503 goto enditer;
00504 }
00505 rpmrc = RPMRC_NOTFOUND;
00506 gi->active = 1;
00507 }
00508 if (gi->mi != NULL) {
00509 Header h = rpmdbNextIterator(gi->mi);
00510 if (h != NULL) {
00511 if (!(gi->flags & RPMGI_NOHEADER))
00512 gi->h = headerLink(h);
00513 sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
00514 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
00515 rpmrc = RPMRC_OK;
00516
00517 }
00518 }
00519 if (rpmrc != RPMRC_OK) {
00520 gi->mi = rpmdbFreeIterator(gi->mi);
00521 goto enditer;
00522 }
00523 break;
00524 case RPMDBI_ADDED:
00525 { rpmte p;
00526
00527 if (!gi->active) {
00528 gi->tsi = rpmtsiInit(gi->ts);
00529 gi->active = 1;
00530 }
00531 if ((p = rpmtsiNext(gi->tsi, TR_ADDED)) != NULL) {
00532 Header h = rpmteHeader(p);
00533 if (h != NULL)
00534 if (!(gi->flags & RPMGI_NOHEADER)) {
00535 gi->h = headerLink(h);
00536 sprintf(hnum, "%u", (unsigned)gi->i);
00537 gi->hdrPath = rpmExpand("added h# ", hnum, NULL);
00538 rpmrc = RPMRC_OK;
00539 h = headerFree(h);
00540 }
00541 }
00542 if (rpmrc != RPMRC_OK) {
00543 gi->tsi = rpmtsiFree(gi->tsi);
00544 goto enditer;
00545 }
00546 } break;
00547 case RPMDBI_HDLIST:
00548 if (!gi->active) {
00549 const char * path = "/usr/share/comps/%{_arch}/hdlist";
00550 gi->fd = rpmgiOpen(path, "r.ufdio");
00551 gi->active = 1;
00552 }
00553 if (gi->fd != NULL) {
00554 Header h = headerRead(gi->fd, HEADER_MAGIC_YES);
00555 if (h != NULL) {
00556 if (!(gi->flags & RPMGI_NOHEADER))
00557 gi->h = headerLink(h);
00558 sprintf(hnum, "%u", (unsigned)gi->i);
00559 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
00560 rpmrc = RPMRC_OK;
00561 h = headerFree(h);
00562 }
00563 }
00564 if (rpmrc != RPMRC_OK) {
00565 if (gi->fd != NULL) (void) Fclose(gi->fd);
00566 gi->fd = NULL;
00567 goto enditer;
00568 }
00569 break;
00570 case RPMDBI_ARGLIST:
00571
00572 if (_rpmgi_debug < 0)
00573 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
00574
00575
00576
00577
00578
00579 rpmrc = RPMRC_NOTFOUND;
00580 while (gi->i < gi->argc) {
00581 if ((rpmrc = rpmgiLoadReadHeader(gi)) == RPMRC_OK)
00582 break;
00583 gi->errors++;
00584 gi->i++;
00585 }
00586
00587 if (rpmrc != RPMRC_OK)
00588 goto enditer;
00589
00590 gi->hdrPath = xstrdup(gi->argv[gi->i]);
00591 break;
00592 case RPMDBI_FTSWALK:
00593 if (gi->argv == NULL)
00594 goto enditer;
00595
00596 if (!gi->active) {
00597 gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
00598
00599 gi->active = 1;
00600 }
00601
00602
00603 rpmrc = rpmgiWalkReadHeader(gi);
00604
00605 if (rpmrc != RPMRC_OK) {
00606 xx = Fts_close(gi->ftsp);
00607 gi->ftsp = NULL;
00608 goto enditer;
00609 }
00610
00611 if (gi->fts != NULL)
00612 gi->hdrPath = xstrdup(gi->fts->fts_path);
00613 break;
00614 }
00615
00616
00617 if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) {
00618
00619 xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL);
00620 }
00621
00622 return rpmrc;
00623
00624 enditer:
00625 if (gi->flags & RPMGI_TSORDER) {
00626 rpmts ts = gi->ts;
00627 rpmps ps;
00628 int i;
00629
00630
00631 xx = rpmtsCloseDB(ts);
00632 ts->dbmode = -1;
00633
00634 xx = rpmtsCheck(ts);
00635
00636
00637 ps = rpmtsProblems(ts);
00638 if (rpmpsNumProblems(ps) > 0) {
00639
00640 rpmMessage(RPMMESS_VERBOSE, _("Failed dependencies:\n"));
00641 if (rpmIsVerbose())
00642 rpmpsPrint(NULL, ps);
00643
00644
00645 if (ts->suggests != NULL && ts->nsuggests > 0) {
00646 rpmMessage(RPMMESS_VERBOSE, _(" Suggested resolutions:\n"));
00647 for (i = 0; i < ts->nsuggests; i++) {
00648 const char * str = ts->suggests[i];
00649
00650 if (str == NULL)
00651 break;
00652
00653 rpmMessage(RPMMESS_VERBOSE, "\t%s\n", str);
00654
00655 ts->suggests[i] = NULL;
00656 str = _free(str);
00657 }
00658 ts->suggests = _free(ts->suggests);
00659 }
00660
00661
00662 }
00663 ps = rpmpsFree(ps);
00664 ts->probs = rpmpsFree(ts->probs);
00665
00666 xx = rpmtsOrder(ts);
00667
00668 gi->tag = RPMDBI_ADDED;
00669 gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER);
00670
00671 }
00672
00673 gi->h = headerFree(gi->h);
00674 gi->hdrPath = _free(gi->hdrPath);
00675 gi->i = -1;
00676 gi->active = 0;
00677 return rpmrc;
00678 }
00679
00680 const char * rpmgiHdrPath(rpmgi gi)
00681 {
00682 return (gi != NULL ? gi->hdrPath : NULL);
00683 }
00684
00685 Header rpmgiHeader(rpmgi gi)
00686 {
00687
00688 return (gi != NULL ? gi->h : NULL);
00689
00690 }
00691
00692 rpmts rpmgiTs(rpmgi gi)
00693 {
00694
00695 return (gi != NULL ? gi->ts : NULL);
00696
00697 }
00698
00699 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
00700 {
00701 gi->ftsOpts = ftsOpts;
00702 gi->flags = flags;
00703 return rpmgiGlobArgv(gi, argv);
00704 }
00705
00706 int rpmgiNumErrors(rpmgi gi)
00707 {
00708 return (gi != NULL ? gi->errors : -1);
00709 }
00710
00711