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