rpm 5.2.1
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> 00009 #include <poptIO.h> 00010 00011 #include <rpmtag.h> 00012 #include <rpmevr.h> 00013 #include "rpmdb.h" 00014 #ifdef NOTYET 00015 #include "rpmds.h" /* XXX ts->suggests, +foo -foo =foo args */ 00016 #endif 00017 00018 #include "rpmte.h" /* XXX rpmtsPrint() */ 00019 #define _RPMTS_INTERNAL /* XXX ts->suggests */ 00020 #include <rpmts.h> 00021 00022 #include "manifest.h" 00023 #define _RPMGI_INTERNAL /* XXX "+bing" args need gi->h. */ 00024 #include "rpmgi.h" 00025 00026 #include <rpmlib.h> 00027 00028 #include <rpmcli.h> 00029 #define _RPMROLLBACK_INTERNAL 00030 #include <rpmrollback.h> 00031 00032 #include "debug.h" 00033 00034 /*@access FD_t @*/ /* XXX void * arg */ 00035 /*@access rpmts @*/ /* XXX ts->suggests */ 00036 /*@access rpmgi @*/ /* XXX gi->h */ 00037 /*@access fnpyKey @*/ /* XXX cast */ 00038 00039 /*@unchecked@*/ 00040 int rpmcliPackagesTotal = 0; 00041 /*@unchecked@*/ 00042 int rpmcliHashesCurrent = 0; 00043 /*@unchecked@*/ 00044 int rpmcliHashesTotal = 0; 00045 /*@unchecked@*/ 00046 rpmuint64_t rpmcliProgressCurrent = 0; 00047 /*@unchecked@*/ 00048 rpmuint64_t rpmcliProgressTotal = 0; 00049 00056 static void printHash(const rpmuint64_t amount, const rpmuint64_t total) 00057 /*@globals rpmcliHashesCurrent, rpmcliHashesTotal, 00058 rpmcliProgressCurrent, fileSystem @*/ 00059 /*@modifies rpmcliHashesCurrent, rpmcliHashesTotal, 00060 rpmcliProgressCurrent, fileSystem @*/ 00061 { 00062 int hashesNeeded; 00063 00064 rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50); 00065 00066 if (rpmcliHashesCurrent != rpmcliHashesTotal) { 00067 float pct = (float) (total ? (((float) amount) / total) : 1); 00068 hashesNeeded = (int)((rpmcliHashesTotal * pct) + 0.5); 00069 while (hashesNeeded > rpmcliHashesCurrent) { 00070 if (isatty (STDOUT_FILENO)) { 00071 int i; 00072 for (i = 0; i < rpmcliHashesCurrent; i++) 00073 (void) putchar ('#'); 00074 for (; i < rpmcliHashesTotal; i++) 00075 (void) putchar (' '); 00076 fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5)); 00077 for (i = 0; i < (rpmcliHashesTotal + 6); i++) 00078 (void) putchar ('\b'); 00079 } else 00080 fprintf(stdout, "#"); 00081 00082 rpmcliHashesCurrent++; 00083 } 00084 (void) fflush(stdout); 00085 00086 if (rpmcliHashesCurrent == rpmcliHashesTotal) { 00087 int i; 00088 rpmcliProgressCurrent++; 00089 if (isatty(STDOUT_FILENO)) { 00090 for (i = 1; i < rpmcliHashesCurrent; i++) 00091 (void) putchar ('#'); 00092 pct = (float) (rpmcliProgressTotal 00093 ? (((float) rpmcliProgressCurrent) / rpmcliProgressTotal) 00094 : 1); 00095 fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5)); 00096 } 00097 fprintf(stdout, "\n"); 00098 } 00099 (void) fflush(stdout); 00100 } 00101 } 00102 00103 void * rpmShowProgress(/*@null@*/ const void * arg, 00104 const rpmCallbackType what, 00105 const rpmuint64_t amount, 00106 const rpmuint64_t total, 00107 /*@null@*/ fnpyKey key, 00108 /*@null@*/ void * data) 00109 /*@globals rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal, 00110 rpmGlobalMacroContext, fileSystem @*/ 00111 /*@modifies rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal, 00112 rpmGlobalMacroContext, fileSystem @*/ 00113 { 00114 /*@-abstract -castexpose @*/ 00115 Header h = (Header) arg; 00116 /*@=abstract =castexpose @*/ 00117 const char * s; 00118 int flags = (int) ((long)data); 00119 void * rc = NULL; 00120 /*@-abstract -assignexpose @*/ 00121 const char * filename = (const char *)key; 00122 /*@=abstract =assignexpose @*/ 00123 static FD_t fd = NULL; 00124 int xx; 00125 00126 switch (what) { 00127 case RPMCALLBACK_INST_OPEN_FILE: 00128 if (filename == NULL || filename[0] == '\0') 00129 return NULL; 00130 fd = Fopen(filename, "r%{?_rpmgio}"); 00131 00132 /* XXX Retry once to handle http:// server timeout reopen's. */ 00133 if (Ferror(fd)) { 00134 int ut = urlPath(filename, NULL); 00135 if (ut == URL_IS_HTTP || ut == URL_IS_HTTPS) { 00136 /* XXX HACK: Fclose(fd) no workie here. */ 00137 fd = Fopen(filename, "r%{?_rpmgio}"); 00138 } 00139 } 00140 00141 /*@-type@*/ /* FIX: still necessary? */ 00142 if (fd == NULL || Ferror(fd)) { 00143 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), filename, 00144 Fstrerror(fd)); 00145 if (fd != NULL) { 00146 xx = Fclose(fd); 00147 fd = NULL; 00148 } 00149 } else 00150 fd = fdLink(fd, "persist (showProgress)"); 00151 /*@=type@*/ 00152 /*@+voidabstract@*/ 00153 return (void *)fd; 00154 /*@=voidabstract@*/ 00155 /*@notreached@*/ break; 00156 00157 case RPMCALLBACK_INST_CLOSE_FILE: 00158 /*@-type@*/ /* FIX: still necessary? */ 00159 fd = fdFree(fd, "persist (showProgress)"); 00160 /*@=type@*/ 00161 if (fd != NULL) { 00162 xx = Fclose(fd); 00163 fd = NULL; 00164 } 00165 break; 00166 00167 case RPMCALLBACK_INST_START: 00168 rpmcliHashesCurrent = 0; 00169 if (h == NULL || !(flags & INSTALL_LABEL)) 00170 break; 00171 /* @todo Remove headerSprintf() on a progress callback. */ 00172 if (flags & INSTALL_HASH) { 00173 s = headerSprintf(h, "%{NAME}", 00174 NULL, rpmHeaderFormats, NULL); 00175 if (isatty (STDOUT_FILENO)) 00176 fprintf(stdout, "%4d:%-23.23s", (int)rpmcliProgressCurrent + 1, s); 00177 else 00178 fprintf(stdout, "%-28.28s", s); 00179 (void) fflush(stdout); 00180 s = _free(s); 00181 } else { 00182 char * t = rpmExpand("%{?___NVRA}%{!?___NVRA:%%{NAME}-%%{VERSION}-%%{RELEASE}}", NULL); 00183 s = headerSprintf(h, t, NULL, rpmHeaderFormats, NULL); 00184 fprintf(stdout, "%s\n", s); 00185 (void) fflush(stdout); 00186 s = _free(s); 00187 t = _free(t); 00188 } 00189 break; 00190 00191 case RPMCALLBACK_TRANS_PROGRESS: 00192 case RPMCALLBACK_INST_PROGRESS: 00193 /*@+relaxtypes@*/ 00194 if (flags & INSTALL_PERCENT) 00195 fprintf(stdout, "%%%% %f\n", (double) (total 00196 ? ((((float) amount) / total) * 100) 00197 : 100.0)); 00198 else if (flags & INSTALL_HASH) 00199 printHash(amount, total); 00200 /*@=relaxtypes@*/ 00201 (void) fflush(stdout); 00202 break; 00203 00204 case RPMCALLBACK_TRANS_START: 00205 rpmcliHashesCurrent = 0; 00206 rpmcliProgressTotal = 1; 00207 rpmcliProgressCurrent = 0; 00208 if (!(flags & INSTALL_LABEL)) 00209 break; 00210 if (flags & INSTALL_HASH) 00211 fprintf(stdout, "%-28s", _("Preparing...")); 00212 else 00213 fprintf(stdout, "%s\n", _("Preparing packages for installation...")); 00214 (void) fflush(stdout); 00215 break; 00216 00217 case RPMCALLBACK_TRANS_STOP: 00218 if (flags & INSTALL_HASH) 00219 printHash(1, 1); /* Fixes "preparing..." progress bar */ 00220 rpmcliProgressTotal = rpmcliPackagesTotal; 00221 rpmcliProgressCurrent = 0; 00222 break; 00223 00224 case RPMCALLBACK_REPACKAGE_START: 00225 rpmcliHashesCurrent = 0; 00226 rpmcliProgressTotal = total; 00227 rpmcliProgressCurrent = 0; 00228 if (!(flags & INSTALL_LABEL)) 00229 break; 00230 if (flags & INSTALL_HASH) 00231 fprintf(stdout, "%-28s\n", _("Repackaging...")); 00232 else 00233 fprintf(stdout, "%s\n", _("Repackaging erased files...")); 00234 (void) fflush(stdout); 00235 break; 00236 00237 case RPMCALLBACK_REPACKAGE_PROGRESS: 00238 if (amount && (flags & INSTALL_HASH)) 00239 printHash(1, 1); /* Fixes "preparing..." progress bar */ 00240 break; 00241 00242 case RPMCALLBACK_REPACKAGE_STOP: 00243 rpmcliProgressTotal = total; 00244 rpmcliProgressCurrent = total; 00245 if (flags & INSTALL_HASH) 00246 printHash(1, 1); /* Fixes "preparing..." progress bar */ 00247 rpmcliProgressTotal = rpmcliPackagesTotal; 00248 rpmcliProgressCurrent = 0; 00249 if (!(flags & INSTALL_LABEL)) 00250 break; 00251 if (flags & INSTALL_HASH) 00252 fprintf(stdout, "%-28s\n", _("Upgrading...")); 00253 else 00254 fprintf(stdout, "%s\n", _("Upgrading packages...")); 00255 (void) fflush(stdout); 00256 break; 00257 00258 case RPMCALLBACK_UNINST_PROGRESS: 00259 break; 00260 case RPMCALLBACK_UNINST_START: 00261 break; 00262 case RPMCALLBACK_UNINST_STOP: 00263 break; 00264 case RPMCALLBACK_UNPACK_ERROR: 00265 break; 00266 case RPMCALLBACK_CPIO_ERROR: 00267 break; 00268 case RPMCALLBACK_SCRIPT_ERROR: 00269 break; 00270 case RPMCALLBACK_UNKNOWN: 00271 default: 00272 break; 00273 } 00274 00275 return rc; 00276 } 00277 00278 int rpmcliInstallProblems(rpmts ts, const char * msg, int rc) 00279 /*@globals fileSystem @*/ 00280 /*@modifies ts, fileSystem @*/ 00281 { 00282 rpmps ps = rpmtsProblems(ts); 00283 00284 if (rc && rpmpsNumProblems(ps) > 0) { 00285 if (msg) 00286 rpmlog(RPMLOG_ERR, "%s:\n", msg); 00287 rpmpsPrint(NULL, ps); 00288 } 00289 ps = rpmpsFree(ps); 00290 return rc; 00291 } 00292 00293 int rpmcliInstallSuggests(rpmts ts) 00294 { 00295 if (ts->suggests != NULL && ts->nsuggests > 0) { 00296 const char * s; 00297 int i; 00298 00299 rpmlog(RPMLOG_NOTICE, _(" Suggested resolutions:\n")); 00300 for (i = 0; i < ts->nsuggests && (s = ts->suggests[i]) != NULL; 00301 ts->suggests[i++] = s = _free(s)) 00302 { 00303 rpmlog(RPMLOG_NOTICE, "\t%s\n", s); 00304 } 00305 ts->suggests = _free(ts->suggests); 00306 } 00307 return 0; 00308 } 00309 00310 int rpmcliInstallCheck(rpmts ts) 00311 { 00312 /*@-evalorder@*/ 00313 return rpmcliInstallProblems(ts, _("Failed dependencies"), rpmtsCheck(ts)); 00314 /*@=evalorder@*/ 00315 } 00316 00317 int rpmcliInstallOrder(rpmts ts) 00318 { 00319 /*@-evalorder@*/ 00320 return rpmcliInstallProblems(ts, _("Ordering problems"), rpmtsOrder(ts)); 00321 /*@=evalorder@*/ 00322 } 00323 00324 int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) 00325 { 00326 /*@-evalorder@*/ 00327 return rpmcliInstallProblems(ts, _("Install/Erase problems"), 00328 rpmtsRun(ts, okProbs, ignoreSet)); 00329 /*@=evalorder@*/ 00330 } 00331 00332 static rpmRC rpmcliEraseElement(rpmts ts, const char * arg) 00333 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00334 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 00335 { 00336 rpmmi mi; 00337 Header h; 00338 rpmRC rc = RPMRC_OK; 00339 int xx; 00340 00341 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0); 00342 if (mi == NULL) 00343 return RPMRC_NOTFOUND; 00344 00345 while ((h = rpmmiNext(mi)) != NULL) { 00346 unsigned int recOffset = rpmmiInstance(mi); 00347 00348 if (recOffset == 0) { /* XXX can't happen. */ 00349 rc = RPMRC_FAIL; 00350 break; 00351 } 00352 xx = rpmtsAddEraseElement(ts, h, recOffset); 00353 } 00354 mi = rpmmiFree(mi); 00355 00356 return 0; 00357 } 00358 00359 static const char * rpmcliWalkFirst(ARGV_t av, miRE mire) 00360 /*@globals fileSystem, internalState @*/ 00361 /*@modifies mire, fileSystem, internalState @*/ 00362 { 00363 /* XXX use global ftsOpts? */ 00364 /* XXX changing FTS_LOGICAL to FTS_PHYSICAL prevents symlink follow. */ 00365 /* XXX FTS_NOCHDIR is automatically assumed for URI's */ 00366 int _ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00367 FTS * ftsp = NULL; 00368 FTSENT * fts; 00369 const char * fn = NULL; 00370 int fts_level = 1; 00371 int xx; 00372 00373 if (av != NULL && av[0] != NULL) 00374 ftsp = Fts_open((char *const *)av, _ftsOpts, NULL); 00375 if (ftsp != NULL) 00376 while((fts = Fts_read(ftsp)) != NULL) { 00377 switch (fts->fts_info) { 00378 /* No-op conditions. */ 00379 case FTS_D: /* preorder directory */ 00380 case FTS_DP: /* postorder directory */ 00381 /* XXX Don't recurse downwards, all elements should be files. */ 00382 if (fts_level > 0 && fts->fts_level >= fts_level) 00383 xx = Fts_set(ftsp, fts, FTS_SKIP); 00384 /*@fallthrough@*/ 00385 case FTS_DOT: /* dot or dot-dot */ 00386 continue; 00387 /*@notreached@*/ /*@switchbreak@*/ break; 00388 case FTS_F: /* regular file */ 00389 if (mireRegexec(mire, fts->fts_accpath, 0) < 0) 00390 continue; 00391 /*@switchbreak@*/ break; 00392 /* Error conditions. */ 00393 case FTS_NS: /* stat(2) failed */ 00394 case FTS_DNR: /* unreadable directory */ 00395 case FTS_ERR: /* error; errno is set */ 00396 case FTS_DC: /* directory that causes cycles */ 00397 case FTS_DEFAULT: /* none of the above */ 00398 case FTS_INIT: /* initialized only */ 00399 case FTS_NSOK: /* no stat(2) requested */ 00400 case FTS_SL: /* symbolic link */ 00401 case FTS_SLNONE: /* symbolic link without target */ 00402 case FTS_W: /* whiteout object */ 00403 default: 00404 goto exit; 00405 /*@notreached@*/ /*@switchbreak@*/ break; 00406 } 00407 00408 /* Stop on first file that matches. */ 00409 fn = xstrdup(fts->fts_accpath); 00410 break; 00411 } 00412 00413 exit: 00414 xx = Fts_close(ftsp); 00415 return fn; 00416 } 00417 00418 static const char * rpmcliInstallElementPath(/*@unused@*/ rpmts ts, 00419 const char * arg) 00420 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00421 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ 00422 { 00423 /* A glob pattern list to match repository directories. */ 00424 const char * fn = rpmExpand( 00425 "%{?_rpmgi_pattern_glob}" 00426 "%{!?_rpmgi_pattern_glob:.}", 00427 NULL 00428 ); 00429 /* A regex pattern list to match candidate *.rpm files. */ 00430 const char * mirePattern = rpmExpand( 00431 "%{?_rpmgi_pattern_regex:%{_rpmgi_pattern_regex ", arg, "}}" 00432 "%{!?_rpmgi_pattern_regex:", arg, "-[^-]+-[^-]+\\.[^.]+\\.rpm$}", 00433 NULL 00434 ); 00435 miRE mire = mireNew(RPMMIRE_REGEX, 0); 00436 ARGV_t dav = NULL; 00437 int dac = 0; 00438 ARGV_t av = NULL; 00439 int xx = mireRegcomp(mire, mirePattern); 00440 int i; 00441 00442 /* Get list of candidate repository patterns. */ 00443 xx = argvSplit(&dav, fn, ":"); 00444 fn = _free(fn); 00445 if (xx || dav == NULL) 00446 goto exit; 00447 00448 dac = argvCount(dav); 00449 for (i = 0; i < dac; i++) { 00450 ARGV_t nav = NULL; 00451 int nac = 0; 00452 00453 /* Insure only directory paths are matched. */ 00454 fn = rpmGetPath(dav[i], "/", NULL); 00455 xx = rpmGlob(fn, &nac, &nav); 00456 00457 /* Insure that final directory paths have trailing '/' */ 00458 if (nav != NULL) 00459 for (i = 0; i < nac; i++) { 00460 char * t = rpmExpand(nav[i], "/", NULL); 00461 nav[i] = _free(nav[i]); 00462 nav[i] = t; 00463 } 00464 00465 /* Append matches to list of repository directories. */ 00466 if (nac > 0 && nav != NULL) 00467 xx = argvAppend(&av, nav); 00468 nav = argvFree(nav); 00469 nac = 0; 00470 fn = _free(fn); 00471 } 00472 00473 /* Walk (possibly multi-root'd) directories, until 1st match is found. */ 00474 fn = rpmcliWalkFirst(av, mire); 00475 00476 exit: 00477 av = argvFree(av); 00478 dav = argvFree(dav); 00479 mire = mireFree(mire); 00480 mirePattern = _free(mirePattern); 00481 00482 return fn; 00483 } 00484 00485 /*@-redef@*/ /* XXX Add rpmfi methods to make rpmRelocation opaque. */ 00486 struct rpmRelocation_s { 00487 /*@only@*/ /*@null@*/ 00488 const char * oldPath; 00489 /*@only@*/ /*@null@*/ 00490 const char * newPath; 00491 }; 00492 /*@=redef@*/ 00493 00495 int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv) 00496 { 00497 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00498 ARGV_t avfn = NULL; 00499 int acfn = 0; 00500 int numFailed = 0; 00501 int numRPMS = 0; 00502 rpmRelocation relocations = NULL; 00503 rpmVSFlags vsflags, ovsflags; 00504 rpmRC rpmrc; 00505 int rc; 00506 int xx; 00507 00508 if (argv == NULL) goto exit; 00509 00510 (void) rpmtsSetGoal(ts, TSM_INSTALL); 00511 rpmcliPackagesTotal = 0; 00512 00513 if (rpmExpandNumeric("%{?_repackage_all_erasures}")) 00514 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE; 00515 00516 (void) rpmtsSetFlags(ts, ia->transFlags); 00517 (void) rpmtsSetDFlags(ts, ia->depFlags); 00518 00519 /* Display and set autorollback goal. */ 00520 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) { 00521 if (ia->arbtid) { 00522 time_t ttid = (time_t)ia->arbtid; 00523 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"), 00524 ctime(&ttid), ia->arbtid); 00525 rpmtsSetARBGoal(ts, ia->arbtid); 00526 } 00527 } 00528 00529 if (ia->installInterfaceFlags & INSTALL_UPGRADE) 00530 vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); 00531 else 00532 vsflags = rpmExpandNumeric("%{?_vsflags_install}"); 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 | RPMVSF_NEEDPAYLOAD)); 00540 00541 { int notifyFlags; 00542 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); 00543 xx = rpmtsSetNotifyCallback(ts, 00544 rpmShowProgress, (void *) ((long)notifyFlags)); 00545 } 00546 00547 if ((relocations = ia->relocations) != NULL) { 00548 while (relocations->oldPath) 00549 relocations++; 00550 if (relocations->newPath == NULL) 00551 relocations = NULL; 00552 } 00553 00554 { /* start-of-transaction-build */ 00555 int tag = (ia->qva_source == RPMQV_FTSWALK) 00556 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST; 00557 rpmgi gi = rpmgiNew(ts, tag, NULL, 0); 00558 rpmgiFlags _giFlags = RPMGI_NONE; 00559 const char * fn = NULL;; 00560 00561 /*@-mods@*/ 00562 if (rpmioFtsOpts == 0) 00563 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00564 /*@=mods@*/ 00565 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, _giFlags); 00566 while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) { 00567 Header h; 00568 00569 fn = _free(fn); 00570 fn = xstrdup(rpmgiHdrPath(gi)); 00571 00572 /* === Check for "+bing" lookaside paths within install transaction. */ 00573 if (fn[0] == '+') { 00574 const char * nfn; 00575 addMacro(NULL, "NEVRA", NULL, &fn[1], RMIL_GLOBAL); 00576 nfn = rpmcliInstallElementPath(ts, &fn[1]); 00577 delMacro(NULL, "NEVRA"); 00578 if (nfn == NULL) { 00579 rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be found\n"), fn); 00580 numFailed++; /* XXX multiple erasures? */ 00581 continue; 00582 } 00583 fn = _free(fn); 00584 fn = nfn; 00585 /* XXX hack into rpmgi innards for now ... */ 00586 h = rpmgiReadHeader(gi, fn); 00587 if (h != NULL) 00588 gi->h = headerLink(h); 00589 (void)headerFree(h); 00590 h = NULL; 00591 } 00592 00593 /* === Check for "-bang" erasures within install transaction. */ 00594 if (fn[0] == '-') { 00595 switch (rpmcliEraseElement(ts, &fn[1])) { 00596 case RPMRC_OK: 00597 numRPMS++; /* XXX multiple erasures? */ 00598 /*@switchbreak@*/ break; 00599 case RPMRC_NOTFOUND: 00600 default: 00601 rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be erased\n"), fn); 00602 numFailed++; /* XXX multiple erasures? */ 00603 goto exit; 00604 /*@notreached@*/ /*@switchbreak@*/ break; 00605 } 00606 continue; 00607 } 00608 00609 h = rpmgiHeader(gi); 00610 if (h == NULL) { 00611 numFailed++; 00612 continue; 00613 } 00614 00615 /* === Check for relocatable package. */ 00616 if (relocations) { 00617 he->tag = RPMTAG_PREFIXES; 00618 xx = headerGet(h, he, 0); 00619 if (xx && he->c == 1) { 00620 relocations->oldPath = xstrdup(he->p.argv[0]); 00621 he->p.ptr = _free(he->p.ptr); 00622 } else { 00623 he->p.ptr = _free(he->p.ptr); 00624 he->tag = RPMTAG_NVRA; 00625 xx = headerGet(h, he, 0); 00626 rpmlog(RPMLOG_ERR, 00627 _("package %s is not relocatable\n"), he->p.str); 00628 he->p.ptr = _free(he->p.ptr); 00629 numFailed++; 00630 goto exit; 00631 /*@notreached@*/ 00632 } 00633 } 00634 00635 /* === On --freshen, verify package is installed and newer. */ 00636 if (ia->installInterfaceFlags & INSTALL_FRESHEN) { 00637 rpmmi mi; 00638 Header oldH; 00639 int count; 00640 00641 he->tag = RPMTAG_NAME; 00642 xx = headerGet(h, he, 0); 00643 assert(xx != 0 && he->p.str != NULL); 00644 mi = rpmtsInitIterator(ts, RPMTAG_NAME, he->p.str, 0); 00645 he->p.ptr = _free(he->p.ptr); 00646 count = rpmmiCount(mi); 00647 while ((oldH = rpmmiNext(mi)) != NULL) { 00648 if (rpmVersionCompare(oldH, h) < 0) 00649 /*@innercontinue@*/ continue; 00650 /* same or newer package already installed */ 00651 count = 0; 00652 /*@innerbreak@*/ break; 00653 } 00654 mi = rpmmiFree(mi); 00655 if (count == 0) 00656 continue; 00657 /* Package is newer than those currently installed. */ 00658 } 00659 00660 /* === Add binary package to transaction set. */ 00661 xx = argvAdd(&avfn, fn); 00662 rc = rpmtsAddInstallElement(ts, h, (fnpyKey)avfn[acfn++], 00663 (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0, 00664 ia->relocations); 00665 00666 if (relocations) 00667 relocations->oldPath = _free(relocations->oldPath); 00668 00669 numRPMS++; 00670 } 00671 00672 fn = _free(fn); 00673 gi = rpmgiFree(gi); 00674 00675 } /* end-of-transaction-build */ 00676 00677 /* XXX exit if the iteration failed. */ 00678 if (rpmrc == RPMRC_FAIL) numFailed = numRPMS; 00679 if (numFailed) goto exit; 00680 00681 if (numRPMS) { 00682 if (!(ia->installInterfaceFlags & INSTALL_NODEPS) 00683 && (rc = rpmcliInstallCheck(ts)) != 0) { 00684 numFailed = numRPMS; 00685 (void) rpmcliInstallSuggests(ts); 00686 } 00687 00688 if (!(ia->installInterfaceFlags & INSTALL_NOORDER) 00689 && (rc = rpmcliInstallOrder(ts)) != 0) 00690 numFailed = numRPMS; 00691 00692 /* Drop added/available package indices and dependency sets. */ 00693 rpmtsClean(ts); 00694 00695 /* XXX Avoid empty transaction msg, run iff there are elements. */ 00696 if (numFailed == 0 && rpmtsNElements(ts) > 0 00697 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter)) != 0) 00698 numFailed += (rc < 0 ? numRPMS : rc); 00699 } 00700 00701 if (numFailed) goto exit; 00702 00703 exit: 00704 avfn = argvFree(avfn); 00705 00706 #ifdef NOTYET /* XXX grrr, segfault in selabel_close */ 00707 if (!(ia->transFlags & RPMTRANS_FLAG_NOCONTEXTS)) 00708 matchpathcon_fini(); 00709 #endif 00710 00711 rpmtsEmpty(ts); 00712 00713 return numFailed; 00714 } 00715 00716 int rpmErase(rpmts ts, QVA_t ia, const char ** argv) 00717 { 00718 int count; 00719 const char ** arg; 00720 int numFailed = 0; 00721 int numRPMS = 0; 00722 rpmVSFlags vsflags, ovsflags; 00723 int rc; 00724 00725 if (argv == NULL) return 0; 00726 00727 vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); 00728 if (ia->qva_flags & VERIFY_DIGEST) 00729 vsflags |= _RPMVSF_NODIGESTS; 00730 if (ia->qva_flags & VERIFY_SIGNATURE) 00731 vsflags |= _RPMVSF_NOSIGNATURES; 00732 if (ia->qva_flags & VERIFY_HDRCHK) 00733 vsflags |= RPMVSF_NOHDRCHK; 00734 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00735 00736 if (rpmExpandNumeric("%{?_repackage_all_erasures}")) 00737 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE; 00738 00739 (void) rpmtsSetFlags(ts, ia->transFlags); 00740 (void) rpmtsSetDFlags(ts, ia->depFlags); 00741 00742 /* Display and set autorollback goal. */ 00743 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) { 00744 if (ia->arbtid) { 00745 time_t ttid = (time_t)ia->arbtid; 00746 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"), 00747 ctime(&ttid), ia->arbtid); 00748 rpmtsSetARBGoal(ts, ia->arbtid); 00749 } 00750 } 00751 00752 #ifdef NOTYET /* XXX no callbacks on erase yet */ 00753 { int notifyFlags; 00754 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); 00755 xx = rpmtsSetNotifyCallback(ts, 00756 rpmShowProgress, (void *) ((long)notifyFlags)); 00757 } 00758 #endif 00759 00760 (void) rpmtsSetGoal(ts, TSM_ERASE); 00761 00762 for (arg = argv; *arg; arg++) { 00763 rpmmi mi; 00764 00765 /* XXX HACK to get rpmdbFindByLabel out of the API */ 00766 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0); 00767 if (mi == NULL) { 00768 rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg); 00769 numFailed++; 00770 } else { 00771 Header h; /* XXX iterator owns the reference */ 00772 count = 0; 00773 while ((h = rpmmiNext(mi)) != NULL) { 00774 unsigned int recOffset = rpmmiInstance(mi); 00775 00776 if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) { 00777 rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages\n"), 00778 *arg); 00779 numFailed++; 00780 /*@innerbreak@*/ break; 00781 } 00782 if (recOffset) { 00783 (void) rpmtsAddEraseElement(ts, h, recOffset); 00784 numRPMS++; 00785 } 00786 } 00787 } 00788 mi = rpmmiFree(mi); 00789 } 00790 00791 if (numFailed == 0 && numRPMS > 0) { 00792 if (!(ia->installInterfaceFlags & INSTALL_NODEPS) 00793 && (rc = rpmcliInstallCheck(ts)) != 0) 00794 numFailed = numRPMS; 00795 00796 if (numFailed == 0 00797 && !(ia->installInterfaceFlags & INSTALL_NOORDER) 00798 && (rc = rpmcliInstallOrder(ts)) != 0) 00799 numFailed = numRPMS; 00800 00801 /* Drop added/available package indices and dependency sets. */ 00802 rpmtsClean(ts); 00803 00804 if (numFailed == 0 00805 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES))) != 0) 00806 numFailed += (rc < 0 ? numRPMS : rc); 00807 00808 } 00809 00810 rpmtsEmpty(ts); 00811 00812 return numFailed; 00813 } 00814 00815 int rpmInstallSource(rpmts ts, const char * arg, 00816 const char ** specFilePtr, const char ** cookie) 00817 { 00818 FD_t fd; 00819 int rc; 00820 00821 fd = Fopen(arg, "r%{?_rpmgio}"); 00822 if (fd == NULL || Ferror(fd)) { 00823 rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), arg, Fstrerror(fd)); 00824 if (fd != NULL) (void) Fclose(fd); 00825 return 1; 00826 } 00827 00828 if (rpmIsVerbose()) 00829 fprintf(stdout, _("Installing %s\n"), arg); 00830 00831 { 00832 rpmVSFlags ovsflags = 00833 rpmtsSetVSFlags(ts, (rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD)); 00834 rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie); 00835 rc = (rpmrc == RPMRC_OK ? 0 : 1); 00836 ovsflags = rpmtsSetVSFlags(ts, ovsflags); 00837 } 00838 if (rc != 0) { 00839 rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), arg); 00840 /*@-unqualifiedtrans@*/ 00841 if (specFilePtr && *specFilePtr) 00842 *specFilePtr = _free(*specFilePtr); 00843 if (cookie && *cookie) 00844 *cookie = _free(*cookie); 00845 /*@=unqualifiedtrans@*/ 00846 } 00847 00848 (void) Fclose(fd); 00849 00850 return rc; 00851 }