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
00155
00156 static rpmRC rpmgiLoadReadHeader(rpmgi gi)
00157
00158
00159 {
00160 rpmRC rpmrc = RPMRC_NOTFOUND;
00161 Header h = NULL;
00162
00163 if (gi->argv != NULL && gi->argv[gi->i] != NULL)
00164 do {
00165 const char * fn;
00166
00167 fn = gi->argv[gi->i];
00168 if (!(gi->flags & RPMGI_NOHEADER)) {
00169 h = rpmgiReadHeader(gi, fn);
00170 if (h != NULL)
00171 rpmrc = RPMRC_OK;
00172 } else
00173 rpmrc = RPMRC_OK;
00174
00175 if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST)
00176 break;
00177 if (errno == ENOENT) {
00178 break;
00179 }
00180
00181
00182 gi->argv[gi->i] = NULL;
00183 rpmrc = rpmgiLoadManifest(gi, fn);
00184 if (rpmrc != RPMRC_OK) {
00185 gi->argv[gi->i] = fn;
00186 break;
00187 }
00188 fn = _free(fn);
00189 rpmrc = RPMRC_NOTFOUND;
00190 } while (1);
00191
00192 if (rpmrc == RPMRC_OK && h != NULL)
00193 gi->h = headerLink(h);
00194 h = headerFree(h);
00195
00196 return rpmrc;
00197 }
00198
00204
00205 static rpmRC rpmgiWalkPathFilter(rpmgi gi)
00206
00207 {
00208 FTSENT * fts = gi->fts;
00209 rpmRC rpmrc = RPMRC_NOTFOUND;
00210 const char * s;
00211
00212 if (_rpmgi_debug < 0)
00213 rpmMessage(RPMMESS_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info),
00214 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
00215 fts->fts_name,
00216 ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : ""));
00217
00218 switch (fts->fts_info) {
00219 case FTS_D:
00220 break;
00221 case FTS_DP:
00222 break;
00223 case FTS_F:
00224
00225 s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm");
00226 if (strcmp(s, ".rpm"))
00227 break;
00228 rpmrc = RPMRC_OK;
00229 break;
00230 case FTS_NS:
00231 case FTS_DNR:
00232 case FTS_ERR:
00233 break;
00234 case FTS_DC:
00235 case FTS_DEFAULT:
00236 case FTS_DOT:
00237 case FTS_INIT:
00238 case FTS_NSOK:
00239 case FTS_SL:
00240 case FTS_SLNONE:
00241 case FTS_W:
00242 default:
00243 break;
00244 }
00245 return rpmrc;
00246 }
00247
00253
00254 static rpmRC rpmgiWalkReadHeader(rpmgi gi)
00255
00256
00257 {
00258 rpmRC rpmrc = RPMRC_NOTFOUND;
00259
00260 if (gi->ftsp != NULL)
00261 while ((gi->fts = Fts_read(gi->ftsp)) != NULL) {
00262 rpmrc = rpmgiWalkPathFilter(gi);
00263 if (rpmrc == RPMRC_OK)
00264 break;
00265 }
00266
00267 if (rpmrc == RPMRC_OK) {
00268 Header h = NULL;
00269 if (!(gi->flags & RPMGI_NOHEADER)) {
00270
00271 if (gi->fts != NULL)
00272 h = rpmgiReadHeader(gi, gi->fts->fts_path);
00273 }
00274 if (h != NULL)
00275 gi->h = headerLink(h);
00276 h = headerFree(h);
00277 }
00278
00279 return rpmrc;
00280 }
00281
00288 static rpmRC rpmgiGlobArgv(rpmgi gi, ARGV_t argv)
00289
00290
00291 {
00292 const char * arg;
00293 rpmRC rpmrc = RPMRC_OK;
00294 int ac = 0;
00295 int xx;
00296
00297
00298 if ((gi->flags & RPMGI_NOGLOB)
00299 || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK))
00300 {
00301 if (argv != NULL) {
00302 while (argv[ac] != NULL)
00303 ac++;
00304
00305 xx = argvAppend(&gi->argv, argv);
00306
00307 }
00308 gi->argc = ac;
00309 return rpmrc;
00310 }
00311
00312 if (argv != NULL)
00313 while ((arg = *argv++) != NULL) {
00314 ARGV_t av = NULL;
00315
00316 xx = rpmGlob(arg, &ac, &av);
00317 xx = argvAppend(&gi->argv, av);
00318 gi->argc += ac;
00319 av = argvFree(av);
00320 ac = 0;
00321 }
00322 return rpmrc;
00323 }
00324
00330 static rpmRC rpmgiInitFilter(rpmgi gi)
00331
00332
00333 {
00334 rpmRC rpmrc = RPMRC_OK;
00335 ARGV_t av;
00336 int res = 0;
00337
00338 gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen);
00339
00340 if (_rpmgi_debug < 0)
00341 fprintf(stderr, "*** gi %p\tmi %p\n", gi, gi->mi);
00342
00343 if (gi->argv != NULL)
00344 for (av = (const char **) gi->argv; *av != NULL; av++) {
00345 int tag = RPMTAG_NAME;
00346 const char * pat;
00347 char * a, * ae;
00348
00349 pat = a = xstrdup(*av);
00350 tag = RPMTAG_NAME;
00351
00352
00353
00354 if ((ae = strchr(a, '=')) != NULL) {
00355 *ae++ = '\0';
00356 tag = tagValue(a);
00357 if (tag < 0) {
00358 rpmError(RPMERR_QUERYINFO, _("unknown tag: \"%s\"\n"), a);
00359 res = 1;
00360 }
00361 pat = ae;
00362 }
00363
00364
00365 if (!res) {
00366 if (_rpmgi_debug < 0)
00367 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (av - gi->argv), *av, tagName(tag), pat);
00368 res = rpmdbSetIteratorRE(gi->mi, tag, RPMMIRE_DEFAULT, pat);
00369 }
00370 a = _free(a);
00371
00372 if (res == 0)
00373 continue;
00374
00375 gi->mi = rpmdbFreeIterator(gi->mi);
00376 rpmrc = RPMRC_FAIL;
00377 break;
00378 }
00379
00380 return rpmrc;
00381 }
00382
00383 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00384 {
00385 if (gi == NULL) return NULL;
00386
00387 if (_rpmgi_debug && msg != NULL)
00388 fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00389
00390 gi->nrefs--;
00391 return NULL;
00392 }
00393
00394 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00395 {
00396 if (gi == NULL) return NULL;
00397 gi->nrefs++;
00398
00399 if (_rpmgi_debug && msg != NULL)
00400 fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00401
00402 return gi;
00403 }
00404
00405 rpmgi rpmgiFree(rpmgi gi)
00406 {
00407 if (gi == NULL)
00408 return NULL;
00409
00410 if (gi->nrefs > 1)
00411 return rpmgiUnlink(gi, __FUNCTION__);
00412
00413 (void) rpmgiUnlink(gi, __FUNCTION__);
00414
00415
00416
00417 gi->hdrPath = _free(gi->hdrPath);
00418 gi->h = headerFree(gi->h);
00419
00420 gi->argv = argvFree(gi->argv);
00421
00422 if (gi->ftsp != NULL) {
00423 int xx;
00424 xx = Fts_close(gi->ftsp);
00425 gi->ftsp = NULL;
00426 gi->fts = NULL;
00427 }
00428 if (gi->fd != NULL) {
00429 (void) Fclose(gi->fd);
00430 gi->fd = NULL;
00431 }
00432 gi->tsi = rpmtsiFree(gi->tsi);
00433 gi->mi = rpmdbFreeIterator(gi->mi);
00434 gi->ts = rpmtsFree(gi->ts);
00435
00436 memset(gi, 0, sizeof(*gi));
00437
00438 gi = _free(gi);
00439
00440
00441 return NULL;
00442 }
00443
00444 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
00445 {
00446 rpmgi gi = xcalloc(1, sizeof(*gi));
00447
00448 if (gi == NULL)
00449 return NULL;
00450
00451 gi->ts = rpmtsLink(ts, __FUNCTION__);
00452 gi->tag = tag;
00453
00454 gi->keyp = keyp;
00455
00456 gi->keylen = keylen;
00457
00458 gi->flags = 0;
00459 gi->active = 0;
00460 gi->i = -1;
00461 gi->hdrPath = NULL;
00462 gi->h = NULL;
00463
00464 gi->tsi = NULL;
00465 gi->mi = NULL;
00466 gi->fd = NULL;
00467 gi->argv = xcalloc(1, sizeof(*gi->argv));
00468 gi->argc = 0;
00469 gi->ftsOpts = 0;
00470 gi->ftsp = NULL;
00471 gi->fts = NULL;
00472
00473 gi = rpmgiLink(gi, __FUNCTION__);
00474
00475 return gi;
00476 }
00477
00478 rpmRC rpmgiNext( rpmgi gi)
00479 {
00480 char hnum[32];
00481 rpmRC rpmrc = RPMRC_NOTFOUND;
00482 int xx;
00483
00484 if (gi == NULL)
00485 return rpmrc;
00486
00487
00488 gi->h = headerFree(gi->h);
00489 gi->hdrPath = _free(gi->hdrPath);
00490 hnum[0] = '\0';
00491
00492
00493 if (++gi->i >= 0)
00494 switch (gi->tag) {
00495 default:
00496 case RPMDBI_PACKAGES:
00497 if (!gi->active) {
00498 rpmrc = rpmgiInitFilter(gi);
00499 if (rpmrc != RPMRC_OK) {
00500 gi->mi = rpmdbFreeIterator(gi->mi);
00501 goto enditer;
00502 }
00503 rpmrc = RPMRC_NOTFOUND;
00504 gi->active = 1;
00505 }
00506 if (gi->mi != NULL) {
00507 Header h = rpmdbNextIterator(gi->mi);
00508 if (h != NULL) {
00509 if (!(gi->flags & RPMGI_NOHEADER))
00510 gi->h = headerLink(h);
00511 sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
00512 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
00513 rpmrc = RPMRC_OK;
00514
00515 }
00516 }
00517 if (rpmrc != RPMRC_OK) {
00518 gi->mi = rpmdbFreeIterator(gi->mi);
00519 goto enditer;
00520 }
00521 break;
00522 case RPMDBI_ADDED:
00523 { rpmte p;
00524
00525 if (!gi->active) {
00526 gi->tsi = rpmtsiInit(gi->ts);
00527 gi->active = 1;
00528 }
00529 if ((p = rpmtsiNext(gi->tsi, TR_ADDED)) != NULL) {
00530 Header h = rpmteHeader(p);
00531 if (h != NULL)
00532 if (!(gi->flags & RPMGI_NOHEADER)) {
00533 gi->h = headerLink(h);
00534 sprintf(hnum, "%u", (unsigned)gi->i);
00535 gi->hdrPath = rpmExpand("added h# ", hnum, NULL);
00536 rpmrc = RPMRC_OK;
00537 h = headerFree(h);
00538 }
00539 }
00540 if (rpmrc != RPMRC_OK) {
00541 gi->tsi = rpmtsiFree(gi->tsi);
00542 goto enditer;
00543 }
00544 } break;
00545 case RPMDBI_HDLIST:
00546 if (!gi->active) {
00547 const char * path = "/usr/share/comps/%{_arch}/hdlist";
00548 gi->fd = rpmgiOpen(path, "r.ufdio");
00549 gi->active = 1;
00550 }
00551 if (gi->fd != NULL) {
00552 Header h = headerRead(gi->fd, HEADER_MAGIC_YES);
00553 if (h != NULL) {
00554 if (!(gi->flags & RPMGI_NOHEADER))
00555 gi->h = headerLink(h);
00556 sprintf(hnum, "%u", (unsigned)gi->i);
00557 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
00558 rpmrc = RPMRC_OK;
00559 h = headerFree(h);
00560 }
00561 }
00562 if (rpmrc != RPMRC_OK) {
00563 if (gi->fd != NULL) (void) Fclose(gi->fd);
00564 gi->fd = NULL;
00565 goto enditer;
00566 }
00567 break;
00568 case RPMDBI_ARGLIST:
00569
00570 if (_rpmgi_debug < 0)
00571 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
00572
00573 rpmrc = rpmgiLoadReadHeader(gi);
00574
00575 if (rpmrc != RPMRC_OK)
00576 goto enditer;
00577
00578 gi->hdrPath = xstrdup(gi->argv[gi->i]);
00579 break;
00580 case RPMDBI_FTSWALK:
00581 if (gi->argv == NULL)
00582 goto enditer;
00583
00584 if (!gi->active) {
00585 gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
00586
00587 gi->active = 1;
00588 }
00589
00590
00591 rpmrc = rpmgiWalkReadHeader(gi);
00592
00593 if (rpmrc != RPMRC_OK) {
00594 xx = Fts_close(gi->ftsp);
00595 gi->ftsp = NULL;
00596 goto enditer;
00597 }
00598
00599 if (gi->fts != NULL)
00600 gi->hdrPath = xstrdup(gi->fts->fts_path);
00601 break;
00602 }
00603
00604
00605 if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) {
00606
00607 xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL);
00608 }
00609
00610 return rpmrc;
00611
00612 enditer:
00613 if (gi->flags & RPMGI_TSORDER) {
00614 rpmts ts = gi->ts;
00615 rpmps ps;
00616 int i;
00617
00618
00619 xx = rpmtsCloseDB(ts);
00620 ts->dbmode = -1;
00621
00622 xx = rpmtsCheck(ts);
00623
00624
00625 ps = rpmtsProblems(ts);
00626 if (rpmpsNumProblems(ps) > 0) {
00627
00628 rpmMessage(RPMMESS_VERBOSE, _("Failed dependencies:\n"));
00629 if (rpmIsVerbose())
00630 rpmpsPrint(NULL, ps);
00631
00632
00633 if (ts->suggests != NULL && ts->nsuggests > 0) {
00634 rpmMessage(RPMMESS_VERBOSE, _(" Suggested resolutions:\n"));
00635 for (i = 0; i < ts->nsuggests; i++) {
00636 const char * str = ts->suggests[i];
00637
00638 if (str == NULL)
00639 break;
00640
00641 rpmMessage(RPMMESS_VERBOSE, "\t%s\n", str);
00642
00643 ts->suggests[i] = NULL;
00644 str = _free(str);
00645 }
00646 ts->suggests = _free(ts->suggests);
00647 }
00648
00649
00650 }
00651 ps = rpmpsFree(ps);
00652 ts->probs = rpmpsFree(ts->probs);
00653
00654 xx = rpmtsOrder(ts);
00655
00656 gi->tag = RPMDBI_ADDED;
00657 gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER);
00658
00659 }
00660
00661 gi->h = headerFree(gi->h);
00662 gi->hdrPath = _free(gi->hdrPath);
00663 gi->i = -1;
00664 gi->active = 0;
00665 return rpmrc;
00666 }
00667
00668 const char * rpmgiHdrPath(rpmgi gi)
00669 {
00670 return (gi != NULL ? gi->hdrPath : NULL);
00671 }
00672
00673 Header rpmgiHeader(rpmgi gi)
00674 {
00675
00676 return (gi != NULL ? gi->h : NULL);
00677
00678 }
00679
00680 rpmts rpmgiTs(rpmgi gi)
00681 {
00682
00683 return (gi != NULL ? gi->ts : NULL);
00684
00685 }
00686
00687 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
00688 {
00689 gi->ftsOpts = ftsOpts;
00690 gi->flags = flags;
00691 return rpmgiGlobArgv(gi, argv);
00692 }
00693
00694