00001
00005 #include "system.h"
00006
00007 #include <rpmio.h>
00008 #include <rpmtag.h>
00009 #define _RPMTS_INTERNAL
00010 #include <rpmcli.h>
00011
00012 #include "rpmdb.h"
00013 #ifdef NOTYET
00014 #include "rpmds.h"
00015 #endif
00016
00017 #include "rpmte.h"
00018
00019 #include "manifest.h"
00020 #include "rpmgi.h"
00021 #include "debug.h"
00022
00023
00024
00025
00026
00027
00028 int rpmcliPackagesTotal = 0;
00029
00030 int rpmcliHashesCurrent = 0;
00031
00032 int rpmcliHashesTotal = 0;
00033
00034 uint64_t rpmcliProgressCurrent = 0;
00035
00036 uint64_t rpmcliProgressTotal = 0;
00037
00044 static void printHash(const uint64_t amount, const uint64_t 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 = (float) (total ? (((float) amount) / total) : 1);
00056 hashesNeeded = (int)((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 = (float) (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 uint64_t amount,
00094 const uint64_t 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 if (filename == NULL || filename[0] == '\0')
00117 return NULL;
00118 fd = Fopen(filename, "r.fdio");
00119
00120 if (fd == NULL || Ferror(fd)) {
00121 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), filename,
00122 Fstrerror(fd));
00123 if (fd != NULL) {
00124 xx = Fclose(fd);
00125 fd = NULL;
00126 }
00127 } else
00128 fd = fdLink(fd, "persist (showProgress)");
00129
00130
00131 return (void *)fd;
00132
00133 break;
00134
00135 case RPMCALLBACK_INST_CLOSE_FILE:
00136
00137 fd = fdFree(fd, "persist (showProgress)");
00138
00139 if (fd != NULL) {
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 NULL, rpmHeaderFormats, NULL);
00153 if (isatty (STDOUT_FILENO))
00154 fprintf(stdout, "%4d:%-23.23s", (int)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 NULL, 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
00171 if (flags & INSTALL_PERCENT)
00172 fprintf(stdout, "%%%% %f\n", (double) (total
00173 ? ((((float) amount) / total) * 100)
00174 : 100.0));
00175 else if (flags & INSTALL_HASH)
00176 printHash(amount, total);
00177
00178 (void) fflush(stdout);
00179 break;
00180
00181 case RPMCALLBACK_TRANS_START:
00182 rpmcliHashesCurrent = 0;
00183 rpmcliProgressTotal = 1;
00184 rpmcliProgressCurrent = 0;
00185 if (!(flags & INSTALL_LABEL))
00186 break;
00187 if (flags & INSTALL_HASH)
00188 fprintf(stdout, "%-28s", _("Preparing..."));
00189 else
00190 fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
00191 (void) fflush(stdout);
00192 break;
00193
00194 case RPMCALLBACK_TRANS_STOP:
00195 if (flags & INSTALL_HASH)
00196 printHash(1, 1);
00197 rpmcliProgressTotal = rpmcliPackagesTotal;
00198 rpmcliProgressCurrent = 0;
00199 break;
00200
00201 case RPMCALLBACK_REPACKAGE_START:
00202 rpmcliHashesCurrent = 0;
00203 rpmcliProgressTotal = total;
00204 rpmcliProgressCurrent = 0;
00205 if (!(flags & INSTALL_LABEL))
00206 break;
00207 if (flags & INSTALL_HASH)
00208 fprintf(stdout, "%-28s\n", _("Repackaging..."));
00209 else
00210 fprintf(stdout, "%s\n", _("Repackaging erased files..."));
00211 (void) fflush(stdout);
00212 break;
00213
00214 case RPMCALLBACK_REPACKAGE_PROGRESS:
00215 if (amount && (flags & INSTALL_HASH))
00216 printHash(1, 1);
00217 break;
00218
00219 case RPMCALLBACK_REPACKAGE_STOP:
00220 rpmcliProgressTotal = total;
00221 rpmcliProgressCurrent = total;
00222 if (flags & INSTALL_HASH)
00223 printHash(1, 1);
00224 rpmcliProgressTotal = rpmcliPackagesTotal;
00225 rpmcliProgressCurrent = 0;
00226 if (!(flags & INSTALL_LABEL))
00227 break;
00228 if (flags & INSTALL_HASH)
00229 fprintf(stdout, "%-28s\n", _("Upgrading..."));
00230 else
00231 fprintf(stdout, "%s\n", _("Upgrading packages..."));
00232 (void) fflush(stdout);
00233 break;
00234
00235 case RPMCALLBACK_UNINST_PROGRESS:
00236 break;
00237 case RPMCALLBACK_UNINST_START:
00238 break;
00239 case RPMCALLBACK_UNINST_STOP:
00240 break;
00241 case RPMCALLBACK_UNPACK_ERROR:
00242 break;
00243 case RPMCALLBACK_CPIO_ERROR:
00244 break;
00245 case RPMCALLBACK_SCRIPT_ERROR:
00246 break;
00247 case RPMCALLBACK_UNKNOWN:
00248 default:
00249 break;
00250 }
00251
00252 return rc;
00253 }
00254
00255 int rpmcliInstallProblems(rpmts ts, const char * msg, int rc)
00256
00257
00258 {
00259 rpmps ps = rpmtsProblems(ts);
00260
00261 if (rc && rpmpsNumProblems(ps) > 0) {
00262 if (msg)
00263 rpmlog(RPMLOG_ERR, "%s:\n", msg);
00264 rpmpsPrint(NULL, ps);
00265 }
00266 ps = rpmpsFree(ps);
00267 return rc;
00268 }
00269
00270 int rpmcliInstallSuggests(rpmts ts)
00271 {
00272 if (ts->suggests != NULL && ts->nsuggests > 0) {
00273 const char * s;
00274 int i;
00275
00276 rpmlog(RPMLOG_NOTICE, _(" Suggested resolutions:\n"));
00277 for (i = 0; i < ts->nsuggests && (s = ts->suggests[i]) != NULL;
00278 ts->suggests[i++] = s = _free(s))
00279 {
00280 rpmlog(RPMLOG_NOTICE, "\t%s\n", s);
00281 }
00282 ts->suggests = _free(ts->suggests);
00283 }
00284 return 0;
00285 }
00286
00287 int rpmcliInstallCheck(rpmts ts)
00288 {
00289
00290 return rpmcliInstallProblems(ts, _("Failed dependencies"), rpmtsCheck(ts));
00291
00292 }
00293
00294 int rpmcliInstallOrder(rpmts ts)
00295 {
00296
00297 return rpmcliInstallProblems(ts, _("Ordering problems"), rpmtsOrder(ts));
00298
00299 }
00300
00301 int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
00302 {
00303
00304 return rpmcliInstallProblems(ts, _("Install/Erase problems"),
00305 rpmtsRun(ts, okProbs, ignoreSet));
00306
00307 }
00308
00309
00311 int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv)
00312 {
00313 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00314 ARGV_t avfn = NULL;
00315 int acfn = 0;
00316 int numFailed = 0;
00317 int numRPMS = 0;
00318 rpmRelocation relocations = NULL;
00319 rpmVSFlags vsflags, ovsflags;
00320 int rc;
00321 int xx;
00322
00323 if (argv == NULL) goto exit;
00324
00325 (void) rpmtsSetGoal(ts, TSM_INSTALL);
00326 rpmcliPackagesTotal = 0;
00327
00328 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
00329 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
00330
00331
00332 if (rpmtsSELinuxEnabled(ts) && !(ia->transFlags & RPMTRANS_FLAG_NOCONTEXTS))
00333 {
00334 const char *fn = rpmGetPath("%{?_install_file_context_path}", NULL);
00335
00336 if (fn != NULL && *fn != '\0')
00337 xx = matchpathcon_init(fn);
00338
00339 fn = _free(fn);
00340 }
00341 (void) rpmtsSetFlags(ts, ia->transFlags);
00342 (void) rpmtsSetDFlags(ts, ia->depFlags);
00343
00344
00345 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
00346 if (ia->arbtid) {
00347 time_t ttid = (time_t)ia->arbtid;
00348 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
00349 ctime(&ttid), ia->arbtid);
00350 rpmtsSetARBGoal(ts, ia->arbtid);
00351 }
00352 }
00353
00354 if (ia->installInterfaceFlags & INSTALL_UPGRADE)
00355 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
00356 else
00357 vsflags = rpmExpandNumeric("%{?_vsflags_install}");
00358 if (ia->qva_flags & VERIFY_DIGEST)
00359 vsflags |= _RPMVSF_NODIGESTS;
00360 if (ia->qva_flags & VERIFY_SIGNATURE)
00361 vsflags |= _RPMVSF_NOSIGNATURES;
00362 if (ia->qva_flags & VERIFY_HDRCHK)
00363 vsflags |= RPMVSF_NOHDRCHK;
00364 ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD));
00365
00366 { int notifyFlags;
00367 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00368 xx = rpmtsSetNotifyCallback(ts,
00369 rpmShowProgress, (void *) ((long)notifyFlags));
00370 }
00371
00372 if ((relocations = ia->relocations) != NULL) {
00373 while (relocations->oldPath)
00374 relocations++;
00375 if (relocations->newPath == NULL)
00376 relocations = NULL;
00377 }
00378
00379 #if defined(REFERENCE_FORNOW)
00380 if (fileURL[0] == '=') {
00381 rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1, NULL, 0);
00382
00383 xx = rpmtsSolve(ts, this, NULL);
00384 if (ts->suggests && ts->nsuggests > 0) {
00385 fileURL = _free(fileURL);
00386 fileURL = ts->suggests[0];
00387 ts->suggests[0] = NULL;
00388 while (ts->nsuggests-- > 0) {
00389 if (ts->suggests[ts->nsuggests] == NULL)
00390 continue;
00391 ts->suggests[ts->nsuggests] = _free(ts->suggests[ts->nsuggests]);
00392 }
00393 ts->suggests = _free(ts->suggests);
00394 rpmlog(RPMLOG_DEBUG, D_("Adding goal: %s\n"), fileURL);
00395 pkgURL[pkgx] = fileURL;
00396 fileURL = NULL;
00397 pkgx++;
00398 }
00399 this = rpmdsFree(this);
00400 } else
00401 #endif
00402
00403 {
00404 int tag = (ia->qva_source == RPMQV_FTSWALK)
00405 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST;
00406 rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
00407 rpmgiFlags _giFlags = RPMGI_NONE;
00408
00409
00410 if (ftsOpts == 0)
00411 ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
00412
00413 rc = rpmgiSetArgs(gi, argv, ftsOpts, _giFlags);
00414 while (rpmgiNext(gi) == RPMRC_OK) {
00415 Header h = rpmgiHeader(gi);
00416 const char * fn;
00417
00418 if (h == NULL) {
00419 numFailed++;
00420 continue;
00421 }
00422 fn = rpmgiHdrPath(gi);
00423
00424
00425 if (relocations) {
00426 he->tag = RPMTAG_PREFIXES;
00427 xx = headerGet(h, he, 0);
00428 if (xx && he->c == 1) {
00429 relocations->oldPath = xstrdup(he->p.argv[0]);
00430 he->p.ptr = _free(he->p.ptr);
00431 } else {
00432 he->p.ptr = _free(he->p.ptr);
00433 he->tag = RPMTAG_NVRA;
00434 xx = headerGet(h, he, 0);
00435 rpmlog(RPMLOG_ERR,
00436 _("package %s is not relocatable\n"), he->p.str);
00437 he->p.ptr = _free(he->p.ptr);
00438 numFailed++;
00439 goto exit;
00440
00441 }
00442 }
00443
00444
00445 if (ia->installInterfaceFlags & INSTALL_FRESHEN) {
00446 rpmdbMatchIterator mi;
00447 Header oldH;
00448 int count;
00449
00450 he->tag = RPMTAG_NAME;
00451 xx = headerGet(h, he, 0);
00452 assert(xx != 0 && he->p.str != NULL);
00453 mi = rpmtsInitIterator(ts, RPMTAG_NAME, he->p.str, 0);
00454 he->p.ptr = _free(he->p.ptr);
00455 count = rpmdbGetIteratorCount(mi);
00456 while ((oldH = rpmdbNextIterator(mi)) != NULL) {
00457 if (rpmVersionCompare(oldH, h) < 0)
00458 continue;
00459
00460 count = 0;
00461 break;
00462 }
00463 mi = rpmdbFreeIterator(mi);
00464 if (count == 0)
00465 continue;
00466
00467 }
00468
00469
00470 xx = argvAdd(&avfn, fn);
00471 rc = rpmtsAddInstallElement(ts, h, (fnpyKey)avfn[acfn++],
00472 (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
00473 ia->relocations);
00474
00475 if (relocations)
00476 relocations->oldPath = _free(relocations->oldPath);
00477
00478 numRPMS++;
00479 }
00480
00481 gi = rpmgiFree(gi);
00482
00483 }
00484
00485 if (numFailed) goto exit;
00486
00487 if (numRPMS) {
00488 if (!(ia->installInterfaceFlags & INSTALL_NODEPS)
00489 && (rc = rpmcliInstallCheck(ts)) != 0) {
00490 numFailed = numRPMS;
00491 (void) rpmcliInstallSuggests(ts);
00492 }
00493
00494 if (!(ia->installInterfaceFlags & INSTALL_NOORDER)
00495 && (rc = rpmcliInstallOrder(ts)) != 0)
00496 numFailed = numRPMS;
00497
00498
00499 rpmtsClean(ts);
00500
00501 if (numFailed == 0
00502 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter)) != 0)
00503 numFailed += (rc < 0 ? numRPMS : rc);
00504 }
00505
00506 if (numFailed) goto exit;
00507
00508 exit:
00509 avfn = argvFree(avfn);
00510
00511 #ifdef NOTYET
00512 if (!(ia->transFlags & RPMTRANS_FLAG_NOCONTEXTS))
00513 matchpathcon_fini();
00514 #endif
00515
00516 rpmtsEmpty(ts);
00517
00518 return numFailed;
00519 }
00520
00521 int rpmErase(rpmts ts, QVA_t ia, const char ** argv)
00522 {
00523 int count;
00524 const char ** arg;
00525 int numFailed = 0;
00526 int numRPMS = 0;
00527 rpmVSFlags vsflags, ovsflags;
00528 int rc;
00529
00530 if (argv == NULL) return 0;
00531
00532 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
00533 if (ia->qva_flags & VERIFY_DIGEST)
00534 vsflags |= _RPMVSF_NODIGESTS;
00535 if (ia->qva_flags & VERIFY_SIGNATURE)
00536 vsflags |= _RPMVSF_NOSIGNATURES;
00537 if (ia->qva_flags & VERIFY_HDRCHK)
00538 vsflags |= RPMVSF_NOHDRCHK;
00539 ovsflags = rpmtsSetVSFlags(ts, vsflags);
00540
00541 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
00542 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
00543
00544 (void) rpmtsSetFlags(ts, ia->transFlags);
00545 (void) rpmtsSetDFlags(ts, ia->depFlags);
00546
00547
00548 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
00549 if (ia->arbtid) {
00550 time_t ttid = (time_t)ia->arbtid;
00551 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
00552 ctime(&ttid), ia->arbtid);
00553 rpmtsSetARBGoal(ts, ia->arbtid);
00554 }
00555 }
00556
00557 #ifdef NOTYET
00558 { int notifyFlags;
00559 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00560 xx = rpmtsSetNotifyCallback(ts,
00561 rpmShowProgress, (void *) ((long)notifyFlags));
00562 }
00563 #endif
00564
00565 (void) rpmtsSetGoal(ts, TSM_ERASE);
00566
00567 for (arg = argv; *arg; arg++) {
00568 rpmdbMatchIterator mi;
00569
00570
00571 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
00572 if (mi == NULL) {
00573 rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
00574 numFailed++;
00575 } else {
00576 Header h;
00577 count = 0;
00578 while ((h = rpmdbNextIterator(mi)) != NULL) {
00579 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
00580
00581 if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) {
00582 rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages\n"),
00583 *arg);
00584 numFailed++;
00585 break;
00586 }
00587 if (recOffset) {
00588 (void) rpmtsAddEraseElement(ts, h, recOffset);
00589 numRPMS++;
00590 }
00591 }
00592 }
00593 mi = rpmdbFreeIterator(mi);
00594 }
00595
00596 if (numFailed == 0 && numRPMS > 0) {
00597 if (!(ia->installInterfaceFlags & INSTALL_NODEPS)
00598 && (rc = rpmcliInstallCheck(ts)) != 0)
00599 numFailed = numRPMS;
00600
00601 if (numFailed == 0
00602 && !(ia->installInterfaceFlags & INSTALL_NOORDER)
00603 && (rc = rpmcliInstallOrder(ts)) != 0)
00604 numFailed = numRPMS;
00605
00606
00607 rpmtsClean(ts);
00608
00609 if (numFailed == 0
00610 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES))) != 0)
00611 numFailed += (rc < 0 ? numRPMS : rc);
00612
00613 }
00614
00615 rpmtsEmpty(ts);
00616
00617 return numFailed;
00618 }
00619
00620 int rpmInstallSource(rpmts ts, const char * arg,
00621 const char ** specFilePtr, const char ** cookie)
00622 {
00623 FD_t fd;
00624 int rc;
00625
00626 fd = Fopen(arg, "r.fdio");
00627 if (fd == NULL || Ferror(fd)) {
00628 rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
00629 if (fd != NULL) (void) Fclose(fd);
00630 return 1;
00631 }
00632
00633 if (rpmIsVerbose())
00634 fprintf(stdout, _("Installing %s\n"), arg);
00635
00636 {
00637 rpmVSFlags ovsflags =
00638 rpmtsSetVSFlags(ts, (rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD));
00639 rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
00640 rc = (rpmrc == RPMRC_OK ? 0 : 1);
00641 ovsflags = rpmtsSetVSFlags(ts, ovsflags);
00642 }
00643 if (rc != 0) {
00644 rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), arg);
00645
00646 if (specFilePtr && *specFilePtr)
00647 *specFilePtr = _free(*specFilePtr);
00648 if (cookie && *cookie)
00649 *cookie = _free(*cookie);
00650
00651 }
00652
00653 (void) Fclose(fd);
00654
00655 return rc;
00656 }