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