00001
00005 #include "system.h"
00006
00007 #include <rpmcli.h>
00008
00009 #include "rpmdb.h"
00010 #include "rpmds.h"
00011
00012 #define _RPMTS_INTERNAL
00013 #include "rpmts.h"
00014
00015 #include "manifest.h"
00016 #include "misc.h"
00017 #include "debug.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 int rpmcliPackagesTotal = 0;
00029
00030 int rpmcliHashesCurrent = 0;
00031
00032 int rpmcliHashesTotal = 0;
00033
00034 int rpmcliProgressCurrent = 0;
00035
00036 int rpmcliProgressTotal = 0;
00037
00044 static void printHash(const unsigned long amount, const unsigned long total)
00045
00046
00047
00048
00049 {
00050 int hashesNeeded;
00051
00052 rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
00053
00054 if (rpmcliHashesCurrent != rpmcliHashesTotal) {
00055 float pct = (total ? (((float) amount) / total) : 1.0);
00056 hashesNeeded = (rpmcliHashesTotal * pct) + 0.5;
00057 while (hashesNeeded > rpmcliHashesCurrent) {
00058 if (isatty (STDOUT_FILENO)) {
00059 int i;
00060 for (i = 0; i < rpmcliHashesCurrent; i++)
00061 (void) putchar ('#');
00062 for (; i < rpmcliHashesTotal; i++)
00063 (void) putchar (' ');
00064 fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
00065 for (i = 0; i < (rpmcliHashesTotal + 6); i++)
00066 (void) putchar ('\b');
00067 } else
00068 fprintf(stdout, "#");
00069
00070 rpmcliHashesCurrent++;
00071 }
00072 (void) fflush(stdout);
00073
00074 if (rpmcliHashesCurrent == rpmcliHashesTotal) {
00075 int i;
00076 rpmcliProgressCurrent++;
00077 if (isatty(STDOUT_FILENO)) {
00078 for (i = 1; i < rpmcliHashesCurrent; i++)
00079 (void) putchar ('#');
00080 pct = (rpmcliProgressTotal
00081 ? (((float) rpmcliProgressCurrent) / rpmcliProgressTotal)
00082 : 1);
00083 fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
00084 }
00085 fprintf(stdout, "\n");
00086 }
00087 (void) fflush(stdout);
00088 }
00089 }
00090
00091 void * rpmShowProgress( const void * arg,
00092 const rpmCallbackType what,
00093 const unsigned long amount,
00094 const unsigned long total,
00095 fnpyKey key,
00096 void * data)
00097
00098
00099
00100
00101 {
00102
00103 Header h = (Header) arg;
00104
00105 char * s;
00106 int flags = (int) ((long)data);
00107 void * rc = NULL;
00108
00109 const char * filename = (const char *)key;
00110
00111 static FD_t fd = NULL;
00112 int xx;
00113
00114 switch (what) {
00115 case RPMCALLBACK_INST_OPEN_FILE:
00116
00117 if (filename == NULL || filename[0] == '\0')
00118 return NULL;
00119
00120 fd = Fopen(filename, "r.ufdio");
00121
00122 if (fd == NULL || Ferror(fd)) {
00123 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), filename,
00124 Fstrerror(fd));
00125 if (fd) {
00126 xx = Fclose(fd);
00127 fd = NULL;
00128 }
00129 } else
00130 fd = fdLink(fd, "persist (showProgress)");
00131
00132 return fd;
00133 break;
00134
00135 case RPMCALLBACK_INST_CLOSE_FILE:
00136
00137 fd = fdFree(fd, "persist (showProgress)");
00138
00139 if (fd) {
00140 xx = Fclose(fd);
00141 fd = NULL;
00142 }
00143 break;
00144
00145 case RPMCALLBACK_INST_START:
00146 rpmcliHashesCurrent = 0;
00147 if (h == NULL || !(flags & INSTALL_LABEL))
00148 break;
00149
00150 if (flags & INSTALL_HASH) {
00151 s = headerSprintf(h, "%{NAME}",
00152 rpmTagTable, rpmHeaderFormats, NULL);
00153 if (isatty (STDOUT_FILENO))
00154 fprintf(stdout, "%4d:%-23.23s", rpmcliProgressCurrent + 1, s);
00155 else
00156 fprintf(stdout, "%-28.28s", s);
00157 (void) fflush(stdout);
00158 s = _free(s);
00159 } else {
00160 s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
00161 rpmTagTable, rpmHeaderFormats, NULL);
00162 fprintf(stdout, "%s\n", s);
00163 (void) fflush(stdout);
00164 s = _free(s);
00165 }
00166 break;
00167
00168 case RPMCALLBACK_TRANS_PROGRESS:
00169 case RPMCALLBACK_INST_PROGRESS:
00170 if (flags & INSTALL_PERCENT)
00171 fprintf(stdout, "%%%% %f\n", (double) (total
00172 ? ((((float) amount) / total) * 100)
00173 : 100.0));
00174 else if (flags & INSTALL_HASH)
00175 printHash(amount, total);
00176 (void) fflush(stdout);
00177 break;
00178
00179 case RPMCALLBACK_TRANS_START:
00180 rpmcliHashesCurrent = 0;
00181 rpmcliProgressTotal = 1;
00182 rpmcliProgressCurrent = 0;
00183 if (!(flags & INSTALL_LABEL))
00184 break;
00185 if (flags & INSTALL_HASH)
00186 fprintf(stdout, "%-28s", _("Preparing..."));
00187 else
00188 fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
00189 (void) fflush(stdout);
00190 break;
00191
00192 case RPMCALLBACK_TRANS_STOP:
00193 if (flags & INSTALL_HASH)
00194 printHash(1, 1);
00195 rpmcliProgressTotal = rpmcliPackagesTotal;
00196 rpmcliProgressCurrent = 0;
00197 break;
00198
00199 case RPMCALLBACK_REPACKAGE_START:
00200 rpmcliHashesCurrent = 0;
00201 rpmcliProgressTotal = total;
00202 rpmcliProgressCurrent = 0;
00203 if (!(flags & INSTALL_LABEL))
00204 break;
00205 if (flags & INSTALL_HASH)
00206 fprintf(stdout, "%-28s\n", _("Repackaging..."));
00207 else
00208 fprintf(stdout, "%s\n", _("Repackaging erased files..."));
00209 (void) fflush(stdout);
00210 break;
00211
00212 case RPMCALLBACK_REPACKAGE_PROGRESS:
00213 if (amount && (flags & INSTALL_HASH))
00214 printHash(1, 1);
00215 break;
00216
00217 case RPMCALLBACK_REPACKAGE_STOP:
00218 rpmcliProgressTotal = total;
00219 rpmcliProgressCurrent = total;
00220 if (flags & INSTALL_HASH)
00221 printHash(1, 1);
00222 rpmcliProgressTotal = rpmcliPackagesTotal;
00223 rpmcliProgressCurrent = 0;
00224 if (!(flags & INSTALL_LABEL))
00225 break;
00226 if (flags & INSTALL_HASH)
00227 fprintf(stdout, "%-28s\n", _("Upgrading..."));
00228 else
00229 fprintf(stdout, "%s\n", _("Upgrading packages..."));
00230 (void) fflush(stdout);
00231 break;
00232
00233 case RPMCALLBACK_UNINST_PROGRESS:
00234 break;
00235 case RPMCALLBACK_UNINST_START:
00236 break;
00237 case RPMCALLBACK_UNINST_STOP:
00238 break;
00239 case RPMCALLBACK_UNPACK_ERROR:
00240 break;
00241 case RPMCALLBACK_CPIO_ERROR:
00242 break;
00243 case RPMCALLBACK_UNKNOWN:
00244 default:
00245 break;
00246 }
00247
00248 return rc;
00249 }
00250
00251 typedef const char * str_t;
00252
00253 struct rpmEIU {
00254 Header h;
00255 FD_t fd;
00256 int numFailed;
00257 int numPkgs;
00258
00259 str_t * pkgURL;
00260
00261 str_t * fnp;
00262
00263 char * pkgState;
00264 int prevx;
00265 int pkgx;
00266 int numRPMS;
00267 int numSRPMS;
00268
00269 str_t * sourceURL;
00270 int isSource;
00271 int argc;
00272
00273 str_t * argv;
00274
00275 rpmRelocation * relocations;
00276 rpmRC rpmrc;
00277 };
00278
00280
00281 int rpmInstall(rpmts ts,
00282 struct rpmInstallArguments_s * ia,
00283 const char ** fileArgv)
00284 {
00285 struct rpmEIU * eiu = memset(alloca(sizeof(*eiu)), 0, sizeof(*eiu));
00286 rpmps ps;
00287 rpmprobFilterFlags probFilter;
00288 rpmRelocation * relocations;
00289 const char * fileURL = NULL;
00290 int stopInstall = 0;
00291 const char ** av = NULL;
00292 rpmVSFlags vsflags, ovsflags, tvsflags;
00293 int ac = 0;
00294 int rc;
00295 int xx;
00296 int i;
00297
00298 if (fileArgv == NULL) goto exit;
00299
00300 ts->goal = TSM_INSTALL;
00301 rpmcliPackagesTotal = 0;
00302
00303 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
00304 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
00305
00306 (void) rpmtsSetFlags(ts, ia->transFlags);
00307 probFilter = ia->probFilter;
00308 relocations = ia->relocations;
00309
00310 if (ia->installInterfaceFlags & INSTALL_UPGRADE)
00311 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
00312 else
00313 vsflags = rpmExpandNumeric("%{?_vsflags_install}");
00314 if (ia->qva_flags & VERIFY_DIGEST)
00315 vsflags |= _RPMVSF_NODIGESTS;
00316 if (ia->qva_flags & VERIFY_SIGNATURE)
00317 vsflags |= _RPMVSF_NOSIGNATURES;
00318 if (ia->qva_flags & VERIFY_HDRCHK)
00319 vsflags |= RPMVSF_NOHDRCHK;
00320 ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD));
00321
00322 { int notifyFlags;
00323 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00324 xx = rpmtsSetNotifyCallback(ts,
00325 rpmShowProgress, (void *) ((long)notifyFlags));
00326 }
00327
00328 if ((eiu->relocations = relocations) != NULL) {
00329 while (eiu->relocations->oldPath)
00330 eiu->relocations++;
00331 if (eiu->relocations->newPath == NULL)
00332 eiu->relocations = NULL;
00333 }
00334
00335
00336
00337
00338 for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) {
00339
00340 av = _free(av); ac = 0;
00341 rc = rpmGlob(*eiu->fnp, &ac, &av);
00342 if (rc || ac == 0) continue;
00343
00344 eiu->argv = xrealloc(eiu->argv, (eiu->argc+ac+1) * sizeof(*eiu->argv));
00345 memcpy(eiu->argv+eiu->argc, av, ac * sizeof(*av));
00346 eiu->argc += ac;
00347 eiu->argv[eiu->argc] = NULL;
00348 }
00349
00350 av = _free(av); ac = 0;
00351
00352 restart:
00353
00354 if (eiu->pkgx >= eiu->numPkgs) {
00355 eiu->numPkgs = eiu->pkgx + eiu->argc;
00356 eiu->pkgURL = xrealloc(eiu->pkgURL,
00357 (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL));
00358 memset(eiu->pkgURL + eiu->pkgx, 0,
00359 ((eiu->argc + 1) * sizeof(*eiu->pkgURL)));
00360 eiu->pkgState = xrealloc(eiu->pkgState,
00361 (eiu->numPkgs + 1) * sizeof(*eiu->pkgState));
00362 memset(eiu->pkgState + eiu->pkgx, 0,
00363 ((eiu->argc + 1) * sizeof(*eiu->pkgState)));
00364 }
00365
00366
00367 for (i = 0; i < eiu->argc; i++) {
00368 fileURL = _free(fileURL);
00369 fileURL = eiu->argv[i];
00370 eiu->argv[i] = NULL;
00371
00372 #ifdef NOTYET
00373 if (fileURL[0] == '=') {
00374 rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1, NULL, 0);
00375
00376 xx = rpmtsSolve(ts, this, NULL);
00377 if (ts->suggests && ts->nsuggests > 0) {
00378 fileURL = _free(fileURL);
00379 fileURL = ts->suggests[0];
00380 ts->suggests[0] = NULL;
00381 while (ts->nsuggests-- > 0) {
00382 if (ts->suggests[ts->nsuggests] == NULL)
00383 continue;
00384 ts->suggests[ts->nsuggests] = _free(ts->suggests[ts->nsuggests]);
00385 }
00386 ts->suggests = _free(ts->suggests);
00387 rpmMessage(RPMMESS_DEBUG, _("Adding goal: %s\n"), fileURL);
00388 eiu->pkgURL[eiu->pkgx] = fileURL;
00389 fileURL = NULL;
00390 eiu->pkgx++;
00391 }
00392 this = rpmdsFree(this);
00393 } else
00394 #endif
00395
00396 switch (urlIsURL(fileURL)) {
00397 case URL_IS_FTP:
00398 case URL_IS_HTTP:
00399 { const char *tfn;
00400
00401 if (rpmIsVerbose())
00402 fprintf(stdout, _("Retrieving %s\n"), fileURL);
00403
00404 { char tfnbuf[64];
00405 const char * rootDir = rpmtsRootDir(ts);
00406 if (!(rootDir && * rootDir))
00407 rootDir = "";
00408 strcpy(tfnbuf, "rpm-xfer.XXXXXX");
00409 (void) mktemp(tfnbuf);
00410 tfn = rpmGenPath(rootDir, "%{_tmppath}/", tfnbuf);
00411 }
00412
00413
00414
00415 rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
00416 rc = urlGetFile(fileURL, tfn);
00417 if (rc < 0) {
00418 rpmMessage(RPMMESS_ERROR,
00419 _("skipping %s - transfer failed - %s\n"),
00420 fileURL, ftpStrerror(rc));
00421 eiu->numFailed++;
00422 eiu->pkgURL[eiu->pkgx] = NULL;
00423 tfn = _free(tfn);
00424 break;
00425 }
00426 eiu->pkgState[eiu->pkgx] = 1;
00427 eiu->pkgURL[eiu->pkgx] = tfn;
00428 eiu->pkgx++;
00429 } break;
00430 case URL_IS_PATH:
00431 default:
00432 eiu->pkgURL[eiu->pkgx] = fileURL;
00433 fileURL = NULL;
00434 eiu->pkgx++;
00435 break;
00436 }
00437 }
00438 fileURL = _free(fileURL);
00439
00440 if (eiu->numFailed) goto exit;
00441
00442
00443 for (eiu->fnp = eiu->pkgURL+eiu->prevx;
00444 *eiu->fnp != NULL;
00445 eiu->fnp++, eiu->prevx++)
00446 {
00447 const char * fileName;
00448
00449 rpmMessage(RPMMESS_DEBUG, "============== %s\n", *eiu->fnp);
00450 (void) urlPath(*eiu->fnp, &fileName);
00451
00452
00453 eiu->fd = Fopen(*eiu->fnp, "r.ufdio");
00454 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00455 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
00456 Fstrerror(eiu->fd));
00457 if (eiu->fd) {
00458 xx = Fclose(eiu->fd);
00459 eiu->fd = NULL;
00460 }
00461 eiu->numFailed++; *eiu->fnp = NULL;
00462 continue;
00463 }
00464
00465
00466 tvsflags = rpmtsSetVSFlags(ts, vsflags);
00467 eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h);
00468 tvsflags = rpmtsSetVSFlags(ts, tvsflags);
00469 xx = Fclose(eiu->fd);
00470 eiu->fd = NULL;
00471
00472 switch (eiu->rpmrc) {
00473 case RPMRC_FAIL:
00474 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *eiu->fnp);
00475 eiu->numFailed++; *eiu->fnp = NULL;
00476 continue;
00477 break;
00478 case RPMRC_NOTFOUND:
00479 goto maybe_manifest;
00480 break;
00481 case RPMRC_NOTTRUSTED:
00482 case RPMRC_NOKEY:
00483 case RPMRC_OK:
00484 default:
00485 break;
00486 }
00487
00488 eiu->isSource = headerIsEntry(eiu->h, RPMTAG_SOURCEPACKAGE);
00489
00490 if (eiu->isSource) {
00491 rpmMessage(RPMMESS_DEBUG, "\tadded source package [%d]\n",
00492 eiu->numSRPMS);
00493 eiu->sourceURL = xrealloc(eiu->sourceURL,
00494 (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL));
00495 eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp;
00496 *eiu->fnp = NULL;
00497 eiu->numSRPMS++;
00498 eiu->sourceURL[eiu->numSRPMS] = NULL;
00499 continue;
00500 }
00501
00502 if (eiu->relocations) {
00503 const char ** paths;
00504 int pft;
00505 int c;
00506
00507 if (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft,
00508 (void **) &paths, &c) && (c == 1))
00509 {
00510 eiu->relocations->oldPath = xstrdup(paths[0]);
00511 paths = headerFreeData(paths, pft);
00512 } else {
00513 const char * name;
00514 xx = headerNVR(eiu->h, &name, NULL, NULL);
00515 rpmMessage(RPMMESS_ERROR,
00516 _("package %s is not relocateable\n"), name);
00517 eiu->numFailed++;
00518 goto exit;
00519
00520 }
00521 }
00522
00523
00524 if (ia->installInterfaceFlags & INSTALL_FRESHEN) {
00525 rpmdbMatchIterator mi;
00526 const char * name;
00527 Header oldH;
00528 int count;
00529
00530 xx = headerNVR(eiu->h, &name, NULL, NULL);
00531 mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0);
00532 count = rpmdbGetIteratorCount(mi);
00533 while ((oldH = rpmdbNextIterator(mi)) != NULL) {
00534 if (rpmVersionCompare(oldH, eiu->h) < 0)
00535 continue;
00536
00537 count = 0;
00538 break;
00539 }
00540 mi = rpmdbFreeIterator(mi);
00541 if (count == 0) {
00542 eiu->h = headerFree(eiu->h);
00543 continue;
00544 }
00545
00546 }
00547
00548
00549 rc = rpmtsAddInstallElement(ts, eiu->h, (fnpyKey)fileName,
00550 (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
00551 relocations);
00552
00553
00554
00555 eiu->h = headerFree(eiu->h);
00556 if (eiu->relocations)
00557 eiu->relocations->oldPath = _free(eiu->relocations->oldPath);
00558
00559 switch(rc) {
00560 case 0:
00561 rpmMessage(RPMMESS_DEBUG, "\tadded binary package [%d]\n",
00562 eiu->numRPMS);
00563 break;
00564 case 1:
00565 rpmMessage(RPMMESS_ERROR,
00566 _("error reading from file %s\n"), *eiu->fnp);
00567 eiu->numFailed++;
00568 goto exit;
00569 break;
00570 case 2:
00571 rpmMessage(RPMMESS_ERROR,
00572 _("file %s requires a newer version of RPM\n"),
00573 *eiu->fnp);
00574 eiu->numFailed++;
00575 goto exit;
00576 break;
00577 }
00578
00579 eiu->numRPMS++;
00580 continue;
00581
00582 maybe_manifest:
00583
00584 eiu->fd = Fopen(*eiu->fnp, "r.fpio");
00585 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00586 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
00587 Fstrerror(eiu->fd));
00588 if (eiu->fd) {
00589 xx = Fclose(eiu->fd);
00590 eiu->fd = NULL;
00591 }
00592 eiu->numFailed++; *eiu->fnp = NULL;
00593 break;
00594 }
00595
00596
00597 rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv);
00598 if (rc != RPMRC_OK)
00599 rpmError(RPMERR_MANIFEST, _("%s: not an rpm package (or package manifest): %s\n"),
00600 *eiu->fnp, Fstrerror(eiu->fd));
00601 xx = Fclose(eiu->fd);
00602 eiu->fd = NULL;
00603
00604
00605 if (rc == RPMRC_OK) {
00606 eiu->prevx++;
00607 goto restart;
00608 }
00609
00610 eiu->numFailed++; *eiu->fnp = NULL;
00611 break;
00612 }
00613
00614 rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"),
00615 eiu->numSRPMS, eiu->numRPMS);
00616
00617 if (eiu->numFailed) goto exit;
00618
00619 if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NODEPS)) {
00620
00621 if (rpmtsCheck(ts)) {
00622 eiu->numFailed = eiu->numPkgs;
00623 stopInstall = 1;
00624 }
00625
00626 ps = rpmtsProblems(ts);
00627 if (!stopInstall && rpmpsNumProblems(ps) > 0) {
00628 rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
00629 rpmpsPrint(NULL, ps);
00630 eiu->numFailed = eiu->numPkgs;
00631 stopInstall = 1;
00632
00633
00634 if (ts->suggests != NULL && ts->nsuggests > 0) {
00635 rpmMessage(RPMMESS_NORMAL, _(" Suggested resolutions:\n"));
00636 for (i = 0; i < ts->nsuggests; i++) {
00637 const char * str = ts->suggests[i];
00638
00639 if (str == NULL)
00640 break;
00641
00642 rpmMessage(RPMMESS_NORMAL, "\t%s\n", str);
00643
00644 ts->suggests[i] = NULL;
00645 str = _free(str);
00646 }
00647 ts->suggests = _free(ts->suggests);
00648 }
00649
00650 }
00651 ps = rpmpsFree(ps);
00652 }
00653
00654 if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
00655 if (rpmtsOrder(ts)) {
00656 eiu->numFailed = eiu->numPkgs;
00657 stopInstall = 1;
00658 }
00659 }
00660
00661 if (eiu->numRPMS && !stopInstall) {
00662
00663 rpmcliPackagesTotal += eiu->numSRPMS;
00664
00665 rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n"));
00666
00667
00668 rpmtsClean(ts);
00669
00670 rc = rpmtsRun(ts, NULL, probFilter);
00671 ps = rpmtsProblems(ts);
00672
00673 if (rc < 0) {
00674 eiu->numFailed += eiu->numRPMS;
00675 } else if (rc > 0) {
00676 eiu->numFailed += rc;
00677 if (rpmpsNumProblems(ps) > 0)
00678 rpmpsPrint(stderr, ps);
00679 }
00680 ps = rpmpsFree(ps);
00681 }
00682
00683 if (eiu->numSRPMS && !stopInstall) {
00684 if (eiu->sourceURL != NULL)
00685 for (i = 0; i < eiu->numSRPMS; i++) {
00686 if (eiu->sourceURL[i] == NULL) continue;
00687 eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio");
00688 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00689 rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
00690 eiu->sourceURL[i], Fstrerror(eiu->fd));
00691 if (eiu->fd) {
00692 xx = Fclose(eiu->fd);
00693 eiu->fd = NULL;
00694 }
00695 continue;
00696 }
00697
00698 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
00699 eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL, NULL);
00700 if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++;
00701 }
00702
00703 xx = Fclose(eiu->fd);
00704 eiu->fd = NULL;
00705 }
00706 }
00707
00708 exit:
00709 if (eiu->pkgURL != NULL)
00710 for (i = 0; i < eiu->numPkgs; i++) {
00711 if (eiu->pkgURL[i] == NULL) continue;
00712 if (eiu->pkgState[i] == 1)
00713 (void) Unlink(eiu->pkgURL[i]);
00714 eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
00715 }
00716 eiu->pkgState = _free(eiu->pkgState);
00717 eiu->pkgURL = _free(eiu->pkgURL);
00718 eiu->argv = _free(eiu->argv);
00719
00720 rpmtsEmpty(ts);
00721
00722 return eiu->numFailed;
00723 }
00724
00725
00726 int rpmErase(rpmts ts,
00727 const struct rpmInstallArguments_s * ia,
00728 const char ** argv)
00729 {
00730 int count;
00731 const char ** arg;
00732 int numFailed = 0;
00733 int stopUninstall = 0;
00734 int numPackages = 0;
00735 rpmVSFlags vsflags, ovsflags;
00736 rpmps ps;
00737
00738 if (argv == NULL) return 0;
00739
00740 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
00741 if (ia->qva_flags & VERIFY_DIGEST)
00742 vsflags |= _RPMVSF_NODIGESTS;
00743 if (ia->qva_flags & VERIFY_SIGNATURE)
00744 vsflags |= _RPMVSF_NOSIGNATURES;
00745 if (ia->qva_flags & VERIFY_HDRCHK)
00746 vsflags |= RPMVSF_NOHDRCHK;
00747 ovsflags = rpmtsSetVSFlags(ts, vsflags);
00748
00749 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
00750 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
00751
00752 (void) rpmtsSetFlags(ts, ia->transFlags);
00753
00754 #ifdef NOTYET
00755 { int notifyFlags;
00756 notifyFlags = ia->eraseInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00757 xx = rpmtsSetNotifyCallback(ts,
00758 rpmShowProgress, (void *) ((long)notifyFlags)
00759 }
00760 #endif
00761
00762 ts->goal = TSM_ERASE;
00763
00764 for (arg = argv; *arg; arg++) {
00765 rpmdbMatchIterator mi;
00766
00767
00768 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
00769 count = rpmdbGetIteratorCount(mi);
00770 if (count <= 0) {
00771 rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
00772 numFailed++;
00773 } else if (!(count == 1 || (ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES))) {
00774 rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
00775 *arg);
00776 numFailed++;
00777 } else {
00778 Header h;
00779 while ((h = rpmdbNextIterator(mi)) != NULL) {
00780 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
00781 if (recOffset) {
00782 (void) rpmtsAddEraseElement(ts, h, recOffset);
00783 numPackages++;
00784 }
00785 }
00786 }
00787 mi = rpmdbFreeIterator(mi);
00788 }
00789
00790 if (!(ia->eraseInterfaceFlags & UNINSTALL_NODEPS)) {
00791
00792 if (rpmtsCheck(ts)) {
00793 numFailed = numPackages;
00794 stopUninstall = 1;
00795 }
00796
00797 ps = rpmtsProblems(ts);
00798 if (!stopUninstall && rpmpsNumProblems(ps) > 0) {
00799 rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
00800 rpmpsPrint(NULL, ps);
00801 numFailed += numPackages;
00802 stopUninstall = 1;
00803 }
00804 ps = rpmpsFree(ps);
00805 }
00806
00807 if (!stopUninstall) {
00808 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_REVERSE));
00809
00810
00811 rpmtsClean(ts);
00812
00813 numPackages = rpmtsRun(ts, NULL, 0);
00814 ps = rpmtsProblems(ts);
00815 if (rpmpsNumProblems(ps) > 0)
00816 rpmpsPrint(NULL, ps);
00817 numFailed += numPackages;
00818 stopUninstall = 1;
00819 ps = rpmpsFree(ps);
00820 }
00821
00822 rpmtsEmpty(ts);
00823
00824 return numFailed;
00825 }
00826
00827 int rpmInstallSource(rpmts ts, const char * arg,
00828 const char ** specFilePtr, const char ** cookie)
00829 {
00830 FD_t fd;
00831 int rc;
00832
00833
00834 fd = Fopen(arg, "r.ufdio");
00835 if (fd == NULL || Ferror(fd)) {
00836 rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
00837 if (fd) (void) Fclose(fd);
00838 return 1;
00839 }
00840
00841 if (rpmIsVerbose())
00842 fprintf(stdout, _("Installing %s\n"), arg);
00843
00844 {
00845 rpmVSFlags ovsflags =
00846 rpmtsSetVSFlags(ts, (rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD));
00847 rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
00848 rc = (rpmrc == RPMRC_OK ? 0 : 1);
00849 ovsflags = rpmtsSetVSFlags(ts, ovsflags);
00850 }
00851 if (rc != 0) {
00852 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
00853
00854 if (specFilePtr && *specFilePtr)
00855 *specFilePtr = _free(*specFilePtr);
00856 if (cookie && *cookie)
00857 *cookie = _free(*cookie);
00858
00859 }
00860
00861 (void) Fclose(fd);
00862
00863 return rc;
00864 }
00865
00866
00867 static int reverse = -1;
00868
00871 static int IDTintcmp(const void * a, const void * b)
00872
00873 {
00874
00875 return ( reverse * (((IDT)a)->val.u32 - ((IDT)b)->val.u32) );
00876
00877 }
00878
00879 IDTX IDTXfree(IDTX idtx)
00880 {
00881 if (idtx) {
00882 int i;
00883 if (idtx->idt)
00884 for (i = 0; i < idtx->nidt; i++) {
00885 IDT idt = idtx->idt + i;
00886 idt->h = headerFree(idt->h);
00887 idt->key = _free(idt->key);
00888 }
00889 idtx->idt = _free(idtx->idt);
00890 idtx = _free(idtx);
00891 }
00892 return NULL;
00893 }
00894
00895 IDTX IDTXnew(void)
00896 {
00897 IDTX idtx = xcalloc(1, sizeof(*idtx));
00898 idtx->delta = 10;
00899 idtx->size = sizeof(*((IDT)0));
00900 return idtx;
00901 }
00902
00903 IDTX IDTXgrow(IDTX idtx, int need)
00904 {
00905 if (need < 0) return NULL;
00906 if (idtx == NULL)
00907 idtx = IDTXnew();
00908 if (need == 0) return idtx;
00909
00910 if ((idtx->nidt + need) > idtx->alloced) {
00911 while (need > 0) {
00912 idtx->alloced += idtx->delta;
00913 need -= idtx->delta;
00914 }
00915 idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
00916 }
00917 return idtx;
00918 }
00919
00920 IDTX IDTXsort(IDTX idtx)
00921 {
00922 if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
00923 qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
00924 return idtx;
00925 }
00926
00927 IDTX IDTXload(rpmts ts, rpmTag tag)
00928 {
00929 IDTX idtx = NULL;
00930 rpmdbMatchIterator mi;
00931 HGE_t hge = (HGE_t) headerGetEntry;
00932 Header h;
00933
00934
00935 mi = rpmtsInitIterator(ts, tag, NULL, 0);
00936 while ((h = rpmdbNextIterator(mi)) != NULL) {
00937 rpmTagType type = RPM_NULL_TYPE;
00938 int_32 count = 0;
00939 int_32 * tidp;
00940
00941 tidp = NULL;
00942 if (!hge(h, tag, &type, (void **)&tidp, &count) || tidp == NULL)
00943 continue;
00944
00945 if (type == RPM_INT32_TYPE && (*tidp == 0 || *tidp == -1))
00946 continue;
00947
00948 idtx = IDTXgrow(idtx, 1);
00949 if (idtx == NULL)
00950 continue;
00951 if (idtx->idt == NULL)
00952 continue;
00953
00954 { IDT idt;
00955
00956 idt = idtx->idt + idtx->nidt;
00957
00958 idt->h = headerLink(h);
00959 idt->key = NULL;
00960 idt->instance = rpmdbGetIteratorOffset(mi);
00961 idt->val.u32 = *tidp;
00962 }
00963 idtx->nidt++;
00964 }
00965 mi = rpmdbFreeIterator(mi);
00966
00967
00968 return IDTXsort(idtx);
00969 }
00970
00971 IDTX IDTXglob(rpmts ts, const char * globstr, rpmTag tag)
00972 {
00973 IDTX idtx = NULL;
00974 HGE_t hge = (HGE_t) headerGetEntry;
00975 Header h;
00976 int_32 * tidp;
00977 FD_t fd;
00978 const char ** av = NULL;
00979 int ac = 0;
00980 rpmRC rpmrc;
00981 int xx;
00982 int i;
00983
00984 av = NULL; ac = 0;
00985 xx = rpmGlob(globstr, &ac, &av);
00986
00987 if (xx == 0)
00988 for (i = 0; i < ac; i++) {
00989 rpmTagType type;
00990 int_32 count;
00991 int isSource;
00992
00993 fd = Fopen(av[i], "r.ufdio");
00994 if (fd == NULL || Ferror(fd)) {
00995 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), av[i],
00996 Fstrerror(fd));
00997 if (fd) (void) Fclose(fd);
00998 continue;
00999 }
01000
01001 rpmrc = rpmReadPackageFile(ts, fd, av[i], &h);
01002 (void) Fclose(fd);
01003 switch (rpmrc) {
01004 default:
01005 goto bottom;
01006 break;
01007 case RPMRC_NOTTRUSTED:
01008 case RPMRC_NOKEY:
01009 case RPMRC_OK:
01010 isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
01011 if (isSource)
01012 goto bottom;
01013 break;
01014 }
01015
01016 tidp = NULL;
01017
01018 if (hge(h, tag, &type, (void **) &tidp, &count) && tidp) {
01019
01020 idtx = IDTXgrow(idtx, 1);
01021 if (idtx == NULL || idtx->idt == NULL)
01022 goto bottom;
01023
01024 { IDT idt;
01025 idt = idtx->idt + idtx->nidt;
01026 idt->h = headerLink(h);
01027 idt->key = av[i];
01028 av[i] = NULL;
01029 idt->instance = 0;
01030 idt->val.u32 = *tidp;
01031 }
01032 idtx->nidt++;
01033 }
01034
01035 bottom:
01036 h = headerFree(h);
01037 }
01038
01039 for (i = 0; i < ac; i++)
01040 av[i] = _free(av[i]);
01041 av = _free(av); ac = 0;
01042
01043 return idtx;
01044 }
01045
01047 int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv)
01048 {
01049 int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
01050 unsigned thistid = 0xffffffff;
01051 unsigned prevtid;
01052 time_t tid;
01053 IDTX itids = NULL;
01054 IDTX rtids = NULL;
01055 IDT rp;
01056 int nrids = 0;
01057 IDT ip;
01058 int niids = 0;
01059 int rc = 0;
01060 int vsflags, ovsflags;
01061 int numAdded;
01062 int numRemoved;
01063 rpmps ps;
01064 int _unsafe_rollbacks = 0;
01065 rpmtransFlags transFlags = ia->transFlags;
01066
01067 if (argv != NULL && *argv != NULL) {
01068 rc = -1;
01069 goto exit;
01070 }
01071
01072 _unsafe_rollbacks = rpmExpandNumeric("%{?_unsafe_rollbacks}");
01073
01074 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
01075 if (ia->qva_flags & VERIFY_DIGEST)
01076 vsflags |= _RPMVSF_NODIGESTS;
01077 if (ia->qva_flags & VERIFY_SIGNATURE)
01078 vsflags |= _RPMVSF_NOSIGNATURES;
01079 if (ia->qva_flags & VERIFY_HDRCHK)
01080 vsflags |= RPMVSF_NOHDRCHK;
01081 vsflags |= RPMVSF_NEEDPAYLOAD;
01082 ovsflags = rpmtsSetVSFlags(ts, vsflags);
01083
01084 (void) rpmtsSetFlags(ts, transFlags);
01085
01086 itids = IDTXload(ts, RPMTAG_INSTALLTID);
01087 if (itids != NULL) {
01088 ip = itids->idt;
01089 niids = itids->nidt;
01090 } else {
01091 ip = NULL;
01092 niids = 0;
01093 }
01094
01095 { const char * globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
01096 if (globstr == NULL || *globstr == '%') {
01097 globstr = _free(globstr);
01098 rc = -1;
01099 goto exit;
01100 }
01101 rtids = IDTXglob(ts, globstr, RPMTAG_REMOVETID);
01102 if (rtids != NULL) {
01103 rp = rtids->idt;
01104 nrids = rtids->nidt;
01105 } else {
01106 rp = NULL;
01107 nrids = 0;
01108 }
01109 globstr = _free(globstr);
01110 }
01111
01112 { int notifyFlags, xx;
01113 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
01114 xx = rpmtsSetNotifyCallback(ts,
01115 rpmShowProgress, (void *) ((long)notifyFlags));
01116 }
01117
01118
01119 do {
01120 prevtid = thistid;
01121 rc = 0;
01122 rpmcliPackagesTotal = 0;
01123 numAdded = 0;
01124 numRemoved = 0;
01125 ia->installInterfaceFlags &= ~ifmask;
01126
01127
01128 thistid = 0;
01129 if (ip != NULL && ip->val.u32 > thistid)
01130 thistid = ip->val.u32;
01131 if (rp != NULL && rp->val.u32 > thistid)
01132 thistid = rp->val.u32;
01133
01134
01135 if (thistid == 0 || thistid < ia->rbtid)
01136 break;
01137
01138
01139 if (_unsafe_rollbacks && thistid <= _unsafe_rollbacks)
01140 break;
01141
01142 rpmtsEmpty(ts);
01143 (void) rpmtsSetFlags(ts, transFlags);
01144
01145
01146 while (rp != NULL && rp->val.u32 == thistid) {
01147
01148 rpmMessage(RPMMESS_DEBUG, "\t+++ install %s\n",
01149 (rp->key ? rp->key : "???"));
01150
01151
01152 rc = rpmtsAddInstallElement(ts, rp->h, (fnpyKey)rp->key,
01153 0, ia->relocations);
01154
01155 if (rc != 0)
01156 goto exit;
01157
01158 numAdded++;
01159 rpmcliPackagesTotal++;
01160 if (!(ia->installInterfaceFlags & ifmask))
01161 ia->installInterfaceFlags |= INSTALL_UPGRADE;
01162
01163 #ifdef NOTYET
01164 rp->h = headerFree(rp->h);
01165 #endif
01166 nrids--;
01167 if (nrids > 0)
01168 rp++;
01169 else
01170 rp = NULL;
01171 }
01172
01173
01174 while (ip != NULL && ip->val.u32 == thistid) {
01175
01176 rpmMessage(RPMMESS_DEBUG,
01177 "\t--- erase h#%u\n", ip->instance);
01178
01179 rc = rpmtsAddEraseElement(ts, ip->h, ip->instance);
01180 if (rc != 0)
01181 goto exit;
01182
01183 numRemoved++;
01184
01185 if (_unsafe_rollbacks)
01186 rpmcliPackagesTotal++;
01187
01188 if (!(ia->installInterfaceFlags & ifmask)) {
01189 ia->installInterfaceFlags |= INSTALL_ERASE;
01190 (void) rpmtsSetFlags(ts, (transFlags | RPMTRANS_FLAG_REVERSE));
01191 }
01192
01193 #ifdef NOTYET
01194 ip->instance = 0;
01195 #endif
01196 niids--;
01197 if (niids > 0)
01198 ip++;
01199 else
01200 ip = NULL;
01201 }
01202
01203
01204 if (rpmcliPackagesTotal <= 0)
01205 break;
01206
01207 tid = (time_t)thistid;
01208 rpmMessage(RPMMESS_NORMAL,
01209 _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
01210 numAdded, numRemoved, ctime(&tid), tid);
01211
01212 rc = rpmtsCheck(ts);
01213 ps = rpmtsProblems(ts);
01214 if (rc != 0 && rpmpsNumProblems(ps) > 0) {
01215 rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
01216 rpmpsPrint(NULL, ps);
01217 ps = rpmpsFree(ps);
01218 goto exit;
01219 }
01220 ps = rpmpsFree(ps);
01221
01222 rc = rpmtsOrder(ts);
01223 if (rc != 0)
01224 goto exit;
01225
01226
01227 rpmtsClean(ts);
01228
01229 rc = rpmtsRun(ts, NULL, (ia->probFilter|RPMPROB_FILTER_OLDPACKAGE));
01230 ps = rpmtsProblems(ts);
01231 if (rc > 0 && rpmpsNumProblems(ps) > 0)
01232 rpmpsPrint(stderr, ps);
01233 ps = rpmpsFree(ps);
01234 if (rc)
01235 goto exit;
01236
01237
01238 if (rtids && !rpmIsDebug()) {
01239 int i;
01240 if (rtids->idt)
01241 for (i = 0; i < rtids->nidt; i++) {
01242 IDT rrp = rtids->idt + i;
01243 if (rrp->val.u32 != thistid)
01244 continue;
01245 if (rrp->key)
01246 (void) unlink(rrp->key);
01247 }
01248 }
01249
01250
01251 } while (1);
01252
01253 exit:
01254 rtids = IDTXfree(rtids);
01255 itids = IDTXfree(itids);
01256
01257 rpmtsEmpty(ts);
01258 (void) rpmtsSetFlags(ts, transFlags);
01259
01260 return rc;
01261 }