00001
00005 #include "system.h"
00006
00007 #include <rpmcli.h>
00008
00009 #include "manifest.h"
00010 #include "misc.h"
00011 #include "debug.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 static int hashesPrinted = 0;
00022
00023 int packagesTotal = 0;
00024 static int progressTotal = 0;
00025 static int progressCurrent = 0;
00026
00029 static void printHash(const unsigned long amount, const unsigned long total)
00030
00031 {
00032 int hashesNeeded;
00033 int hashesTotal = 50;
00034
00035 if (isatty (STDOUT_FILENO))
00036 hashesTotal = 44;
00037
00038 if (hashesPrinted != hashesTotal) {
00039 hashesNeeded = hashesTotal * (total ? (((float) amount) / total) : 1);
00040 while (hashesNeeded > hashesPrinted) {
00041 if (isatty (STDOUT_FILENO)) {
00042 int i;
00043 for (i = 0; i < hashesPrinted; i++) (void) putchar ('#');
00044 for (; i < hashesTotal; i++) (void) putchar (' ');
00045 printf ("(%3d%%)",
00046 (int)(100 * (total ? (((float) amount) / total) : 1)));
00047 for (i = 0; i < (hashesTotal + 6); i++) (void) putchar ('\b');
00048 } else
00049 fprintf(stdout, "#");
00050
00051 hashesPrinted++;
00052 }
00053 (void) fflush(stdout);
00054 hashesPrinted = hashesNeeded;
00055
00056 if (hashesPrinted == hashesTotal) {
00057 int i;
00058 progressCurrent++;
00059 for (i = 1; i < hashesPrinted; i++) (void) putchar ('#');
00060 printf (" [%3d%%]\n", (int)(100 * (progressTotal ?
00061 (((float) progressCurrent) / progressTotal) : 1)));
00062 }
00063 (void) fflush(stdout);
00064 }
00065 }
00066
00067 void * rpmShowProgress( const void * arg,
00068 const rpmCallbackType what,
00069 const unsigned long amount,
00070 const unsigned long total,
00071 const void * pkgKey,
00072 void * data)
00073
00074 {
00075
00076 Header h = (Header) arg;
00077
00078 char * s;
00079 int flags = (int) ((long)data);
00080 void * rc = NULL;
00081 const char * filename = pkgKey;
00082 static FD_t fd = NULL;
00083
00084 switch (what) {
00085 case RPMCALLBACK_INST_OPEN_FILE:
00086 if (filename == NULL || filename[0] == '\0')
00087 return NULL;
00088 fd = Fopen(filename, "r.ufdio");
00089 if (fd)
00090 fd = fdLink(fd, "persist (showProgress)");
00091 return fd;
00092 break;
00093
00094 case RPMCALLBACK_INST_CLOSE_FILE:
00095 fd = fdFree(fd, "persist (showProgress)");
00096 if (fd) {
00097 (void) Fclose(fd);
00098 fd = NULL;
00099 }
00100 break;
00101
00102 case RPMCALLBACK_INST_START:
00103 hashesPrinted = 0;
00104 if (h == NULL || !(flags & INSTALL_LABEL))
00105 break;
00106 if (flags & INSTALL_HASH) {
00107 s = headerSprintf(h, "%{NAME}",
00108 rpmTagTable, rpmHeaderFormats, NULL);
00109 if (isatty (STDOUT_FILENO))
00110 fprintf(stdout, "%4d:%-23.23s", progressCurrent + 1, s);
00111 (void) fflush(stdout);
00112 s = _free(s);
00113 } else {
00114 s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
00115 rpmTagTable, rpmHeaderFormats, NULL);
00116 fprintf(stdout, "%s\n", s);
00117 (void) fflush(stdout);
00118 s = _free(s);
00119 }
00120 break;
00121
00122 case RPMCALLBACK_TRANS_PROGRESS:
00123 case RPMCALLBACK_INST_PROGRESS:
00124 if (flags & INSTALL_PERCENT)
00125 fprintf(stdout, "%%%% %f\n", (double) (total
00126 ? ((((float) amount) / total) * 100)
00127 : 100.0));
00128 else if (flags & INSTALL_HASH)
00129 printHash(amount, total);
00130 (void) fflush(stdout);
00131 break;
00132
00133 case RPMCALLBACK_TRANS_START:
00134 hashesPrinted = 0;
00135 progressTotal = 1;
00136 progressCurrent = 0;
00137 if (!(flags & INSTALL_LABEL))
00138 break;
00139 if (flags & INSTALL_HASH)
00140 fprintf(stdout, "%-28s", _("Preparing..."));
00141 else
00142 printf("%s\n", _("Preparing packages for installation..."));
00143 (void) fflush(stdout);
00144 break;
00145
00146 case RPMCALLBACK_TRANS_STOP:
00147 if (flags & INSTALL_HASH)
00148 printHash(1, 1);
00149 progressTotal = packagesTotal;
00150 progressCurrent = 0;
00151 break;
00152
00153 case RPMCALLBACK_UNINST_PROGRESS:
00154 case RPMCALLBACK_UNINST_START:
00155 case RPMCALLBACK_UNINST_STOP:
00156
00157 break;
00158 }
00159
00160 return rc;
00161 }
00162
00163 typedef const char * str_t;
00164
00165 struct rpmEIU {
00166 rpmTransactionSet ts;
00167 rpmdb db;
00168 Header h;
00169 FD_t fd;
00170 int numFailed;
00171 int numPkgs;
00172 str_t * pkgURL;
00173 str_t * fnp;
00174 char * pkgState;
00175 int prevx;
00176 int pkgx;
00177 int numRPMS;
00178 int numSRPMS;
00179 str_t * sourceURL;
00180 int isSource;
00181 int argc;
00182 str_t * argv;
00183 rpmRelocation * relocations;
00184 rpmRC rpmrc;
00185 };
00186
00188 int rpmInstall(const char * rootdir, const char ** fileArgv,
00189 rpmtransFlags transFlags,
00190 rpmInstallInterfaceFlags interfaceFlags,
00191 rpmprobFilterFlags probFilter,
00192 rpmRelocation * relocations)
00193 {
00194 struct rpmEIU * eiu = alloca(sizeof(*eiu));
00195 int notifyFlags = interfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00196 const char * fileURL = NULL;
00197 int stopInstall = 0;
00198 const char ** av = NULL;
00199 int ac = 0;
00200 int rc;
00201 int xx;
00202 int i;
00203
00204 if (fileArgv == NULL) return 0;
00205
00206 memset(eiu, 0, sizeof(*eiu));
00207 eiu->numPkgs = 0;
00208 eiu->prevx = 0;
00209 eiu->pkgx = 0;
00210
00211 if ((eiu->relocations = relocations) != NULL) {
00212 while (eiu->relocations->oldPath)
00213 eiu->relocations++;
00214 if (eiu->relocations->newPath == NULL)
00215 eiu->relocations = NULL;
00216 }
00217
00218
00219
00220 for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) {
00221
00222 av = _free(av); ac = 0;
00223 rc = rpmGlob(*eiu->fnp, &ac, &av);
00224 if (rc || ac == 0) continue;
00225
00226 eiu->argv = xrealloc(eiu->argv, (eiu->argc+ac+1) * sizeof(*eiu->argv));
00227 memcpy(eiu->argv+eiu->argc, av, ac * sizeof(*av));
00228 eiu->argc += ac;
00229 eiu->argv[eiu->argc] = NULL;
00230 }
00231 av = _free(av); ac = 0;
00232
00233 restart:
00234
00235 if (eiu->pkgx >= eiu->numPkgs) {
00236 eiu->numPkgs = eiu->pkgx + eiu->argc;
00237 eiu->pkgURL = xrealloc(eiu->pkgURL,
00238 (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL));
00239 memset(eiu->pkgURL + eiu->pkgx, 0,
00240 ((eiu->argc + 1) * sizeof(*eiu->pkgURL)));
00241 eiu->pkgState = xrealloc(eiu->pkgState,
00242 (eiu->numPkgs + 1) * sizeof(*eiu->pkgState));
00243 memset(eiu->pkgState + eiu->pkgx, 0,
00244 ((eiu->argc + 1) * sizeof(*eiu->pkgState)));
00245 }
00246
00247
00248 for (i = 0; i < eiu->argc; i++) {
00249 fileURL = _free(fileURL);
00250 fileURL = eiu->argv[i];
00251 eiu->argv[i] = NULL;
00252
00253 switch (urlIsURL(fileURL)) {
00254 case URL_IS_FTP:
00255 case URL_IS_HTTP:
00256 { const char *tfn;
00257
00258 if (rpmIsVerbose())
00259 fprintf(stdout, _("Retrieving %s\n"), fileURL);
00260
00261 { char tfnbuf[64];
00262 strcpy(tfnbuf, "rpm-xfer.XXXXXX");
00263 mktemp(tfnbuf) ;
00264 tfn = rpmGenPath(rootdir, "%{_tmppath}/", tfnbuf);
00265 }
00266
00267
00268
00269 rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
00270 rc = urlGetFile(fileURL, tfn);
00271 if (rc < 0) {
00272 rpmMessage(RPMMESS_ERROR,
00273 _("skipping %s - transfer failed - %s\n"),
00274 fileURL, ftpStrerror(rc));
00275 eiu->numFailed++;
00276 eiu->pkgURL[eiu->pkgx] = NULL;
00277 tfn = _free(tfn);
00278 break;
00279 }
00280 eiu->pkgState[eiu->pkgx] = 1;
00281 eiu->pkgURL[eiu->pkgx] = tfn;
00282 eiu->pkgx++;
00283 } break;
00284 case URL_IS_PATH:
00285 default:
00286 eiu->pkgURL[eiu->pkgx] = fileURL;
00287 fileURL = NULL;
00288 eiu->pkgx++;
00289 break;
00290 }
00291 }
00292 fileURL = _free(fileURL);
00293
00294 if (eiu->numFailed) goto exit;
00295
00296
00297 for (eiu->fnp = eiu->pkgURL+eiu->prevx;
00298 *eiu->fnp != NULL;
00299 eiu->fnp++, eiu->prevx++)
00300 {
00301 const char * fileName;
00302
00303 rpmMessage(RPMMESS_DEBUG, "============== %s\n", *eiu->fnp);
00304 (void) urlPath(*eiu->fnp, &fileName);
00305
00306
00307 eiu->fd = Fopen(*eiu->fnp, "r.ufdio");
00308 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00309 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
00310 Fstrerror(eiu->fd));
00311 if (eiu->fd) {
00312 xx = Fclose(eiu->fd);
00313 eiu->fd = NULL;
00314 }
00315 eiu->numFailed++; *eiu->fnp = NULL;
00316 continue;
00317 }
00318
00319
00320 eiu->rpmrc = rpmReadPackageHeader(eiu->fd, &eiu->h,
00321 &eiu->isSource, NULL, NULL);
00322
00323 xx = Fclose(eiu->fd);
00324 eiu->fd = NULL;
00325
00326 if (eiu->rpmrc == RPMRC_FAIL || eiu->rpmrc == RPMRC_SHORTREAD) {
00327 eiu->numFailed++; *eiu->fnp = NULL;
00328 continue;
00329 }
00330
00331 if (eiu->isSource &&
00332 (eiu->rpmrc == RPMRC_OK || eiu->rpmrc == RPMRC_BADSIZE))
00333 {
00334 rpmMessage(RPMMESS_DEBUG, "\tadded source package [%d]\n",
00335 eiu->numSRPMS);
00336 eiu->sourceURL = xrealloc(eiu->sourceURL,
00337 (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL));
00338 eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp;
00339 *eiu->fnp = NULL;
00340 eiu->numSRPMS++;
00341 eiu->sourceURL[eiu->numSRPMS] = NULL;
00342 continue;
00343 }
00344
00345 if (eiu->rpmrc == RPMRC_OK || eiu->rpmrc == RPMRC_BADSIZE) {
00346 if (eiu->db == NULL) {
00347 int mode = (transFlags & RPMTRANS_FLAG_TEST)
00348 ? O_RDONLY : (O_RDWR | O_CREAT);
00349
00350 if (rpmdbOpen(rootdir, &eiu->db, mode, 0644)) {
00351 const char *dn;
00352 dn = rpmGetPath( (rootdir ? rootdir : ""),
00353 "%{_dbpath}", NULL);
00354 rpmMessage(RPMMESS_ERROR,
00355 _("cannot open Packages database in %s\n"), dn);
00356 dn = _free(dn);
00357 eiu->numFailed++; *eiu->fnp = NULL;
00358 break;
00359 }
00360
00361 eiu->ts = rpmtransCreateSet(eiu->db, rootdir);
00362
00363 }
00364
00365 if (eiu->relocations) {
00366 const char ** paths;
00367 int pft;
00368 int c;
00369
00370 if (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft,
00371 (void **) &paths, &c) && (c == 1)) {
00372 eiu->relocations->oldPath = xstrdup(paths[0]);
00373 paths = headerFreeData(paths, pft);
00374 } else {
00375 const char * name;
00376 xx = headerNVR(eiu->h, &name, NULL, NULL);
00377 rpmMessage(RPMMESS_ERROR,
00378 _("package %s is not relocateable\n"), name);
00379 eiu->numFailed++;
00380 goto exit;
00381
00382 }
00383 }
00384
00385
00386 if (interfaceFlags & INSTALL_FRESHEN) {
00387 rpmdbMatchIterator mi;
00388 const char * name;
00389 Header oldH;
00390 int count;
00391
00392 xx = headerNVR(eiu->h, &name, NULL, NULL);
00393
00394 mi = rpmdbInitIterator(eiu->db, RPMTAG_NAME, name, 0);
00395
00396 count = rpmdbGetIteratorCount(mi);
00397 while ((oldH = rpmdbNextIterator(mi)) != NULL) {
00398 if (rpmVersionCompare(oldH, eiu->h) < 0)
00399 continue;
00400
00401 count = 0;
00402 break;
00403 }
00404 mi = rpmdbFreeIterator(mi);
00405 if (count == 0) {
00406 eiu->h = headerFree(eiu->h);
00407 continue;
00408 }
00409
00410 }
00411
00412 rc = rpmtransAddPackage(eiu->ts, eiu->h, NULL, fileName,
00413 (interfaceFlags & INSTALL_UPGRADE) != 0,
00414 relocations);
00415
00416 eiu->h = headerFree(eiu->h);
00417 if (eiu->relocations)
00418 eiu->relocations->oldPath = _free(eiu->relocations->oldPath);
00419
00420 switch(rc) {
00421 case 0:
00422 rpmMessage(RPMMESS_DEBUG, "\tadded binary package [%d]\n",
00423 eiu->numRPMS);
00424 break;
00425 case 1:
00426 rpmMessage(RPMMESS_ERROR,
00427 _("error reading from file %s\n"), *eiu->fnp);
00428 eiu->numFailed++;
00429 goto exit;
00430 break;
00431 case 2:
00432 rpmMessage(RPMMESS_ERROR,
00433 _("file %s requires a newer version of RPM\n"),
00434 *eiu->fnp);
00435 eiu->numFailed++;
00436 goto exit;
00437 break;
00438 }
00439
00440 eiu->numRPMS++;
00441 continue;
00442 }
00443
00444 if (eiu->rpmrc != RPMRC_BADMAGIC) {
00445 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *eiu->fnp);
00446 eiu->numFailed++; *eiu->fnp = NULL;
00447 break;
00448 }
00449
00450
00451 eiu->fd = Fopen(*eiu->fnp, "r.fpio");
00452 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00453 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
00454 Fstrerror(eiu->fd));
00455 if (eiu->fd) {
00456 xx = Fclose(eiu->fd);
00457 eiu->fd = NULL;
00458 }
00459 eiu->numFailed++; *eiu->fnp = NULL;
00460 break;
00461 }
00462
00463
00464 rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv);
00465 if (rc)
00466 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00467 *eiu->fnp, Fstrerror(eiu->fd));
00468 xx = Fclose(eiu->fd);
00469 eiu->fd = NULL;
00470
00471
00472 if (rc == 0) {
00473 eiu->prevx++;
00474 goto restart;
00475 }
00476
00477 eiu->numFailed++; *eiu->fnp = NULL;
00478 break;
00479 }
00480
00481 rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"),
00482 eiu->numSRPMS, eiu->numRPMS);
00483
00484 if (eiu->numFailed) goto exit;
00485
00486 if (eiu->numRPMS && !(interfaceFlags & INSTALL_NODEPS)) {
00487 rpmDependencyConflict conflicts;
00488 int numConflicts;
00489
00490 if (rpmdepCheck(eiu->ts, &conflicts, &numConflicts)) {
00491 eiu->numFailed = eiu->numPkgs;
00492 stopInstall = 1;
00493 }
00494
00495 if (!stopInstall && conflicts) {
00496 rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
00497 printDepProblems(stderr, conflicts, numConflicts);
00498 conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
00499 eiu->numFailed = eiu->numPkgs;
00500 stopInstall = 1;
00501 }
00502 }
00503
00504 if (eiu->numRPMS && !(interfaceFlags & INSTALL_NOORDER)) {
00505 if (rpmdepOrder(eiu->ts)) {
00506 eiu->numFailed = eiu->numPkgs;
00507 stopInstall = 1;
00508 }
00509 }
00510
00511 if (eiu->numRPMS && !stopInstall) {
00512 rpmProblemSet probs = NULL;
00513
00514 packagesTotal = eiu->numRPMS + eiu->numSRPMS;
00515
00516 rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n"));
00517 rc = rpmRunTransactions(eiu->ts, rpmShowProgress,
00518 (void *) ((long)notifyFlags),
00519 NULL, &probs, transFlags, probFilter);
00520
00521 if (rc < 0) {
00522 eiu->numFailed += eiu->numRPMS;
00523 } else if (rc > 0) {
00524 eiu->numFailed += rc;
00525 rpmProblemSetPrint(stderr, probs);
00526 }
00527
00528 if (probs != NULL) rpmProblemSetFree(probs);
00529 }
00530
00531 if (eiu->numSRPMS && !stopInstall) {
00532 if (eiu->sourceURL != NULL)
00533 for (i = 0; i < eiu->numSRPMS; i++) {
00534 if (eiu->sourceURL[i] == NULL) continue;
00535 eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio");
00536 if (eiu->fd == NULL || Ferror(eiu->fd)) {
00537 rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
00538 eiu->sourceURL[i], Fstrerror(eiu->fd));
00539 if (eiu->fd) {
00540 xx = Fclose(eiu->fd);
00541 eiu->fd = NULL;
00542 }
00543 continue;
00544 }
00545
00546 if (!(transFlags & RPMTRANS_FLAG_TEST)) {
00547 eiu->rpmrc = rpmInstallSourcePackage(rootdir, eiu->fd, NULL,
00548 rpmShowProgress, (void *) ((long)notifyFlags), NULL);
00549 if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++;
00550 }
00551
00552 xx = Fclose(eiu->fd);
00553 eiu->fd = NULL;
00554 }
00555 }
00556
00557 exit:
00558 eiu->ts = rpmtransFree(eiu->ts);
00559 if (eiu->pkgURL != NULL)
00560 for (i = 0; i < eiu->numPkgs; i++) {
00561 if (eiu->pkgURL[i] == NULL) continue;
00562 if (eiu->pkgState[i] == 1)
00563 (void) Unlink(eiu->pkgURL[i]);
00564 eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
00565 }
00566 eiu->pkgState = _free(eiu->pkgState);
00567 eiu->pkgURL = _free(eiu->pkgURL);
00568 eiu->argv = _free(eiu->argv);
00569 if (eiu->db != NULL) {
00570 xx = rpmdbClose(eiu->db);
00571 eiu->db = NULL;
00572 }
00573 return eiu->numFailed;
00574 }
00575
00576 int rpmErase(const char * rootdir, const char ** argv,
00577 rpmtransFlags transFlags,
00578 rpmEraseInterfaceFlags interfaceFlags)
00579 {
00580 rpmdb db;
00581 int mode;
00582 int count;
00583 const char ** arg;
00584 int numFailed = 0;
00585 rpmTransactionSet ts;
00586 rpmDependencyConflict conflicts;
00587 int numConflicts;
00588 int stopUninstall = 0;
00589 int numPackages = 0;
00590 rpmProblemSet probs;
00591
00592 if (argv == NULL) return 0;
00593
00594 if (transFlags & RPMTRANS_FLAG_TEST)
00595 mode = O_RDONLY;
00596 else
00597 mode = O_RDWR | O_EXCL;
00598
00599 if (rpmdbOpen(rootdir, &db, mode, 0644)) {
00600 const char *dn;
00601 dn = rpmGetPath( (rootdir ? rootdir : ""), "%{_dbpath}", NULL);
00602 rpmMessage(RPMMESS_ERROR, _("cannot open %s/packages.rpm\n"), dn);
00603 dn = _free(dn);
00604 return -1;
00605 }
00606
00607 ts = rpmtransCreateSet(db, rootdir);
00608 for (arg = argv; *arg; arg++) {
00609 rpmdbMatchIterator mi;
00610
00611
00612 mi = rpmdbInitIterator(db, RPMDBI_LABEL, *arg, 0);
00613 count = rpmdbGetIteratorCount(mi);
00614 if (count <= 0) {
00615 rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
00616 numFailed++;
00617 } else if (!(count == 1 || (interfaceFlags & UNINSTALL_ALLMATCHES))) {
00618 rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
00619 *arg);
00620 numFailed++;
00621 } else {
00622 Header h;
00623 while ((h = rpmdbNextIterator(mi)) != NULL) {
00624 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
00625 if (recOffset) {
00626 (void) rpmtransRemovePackage(ts, recOffset);
00627 numPackages++;
00628 }
00629 }
00630 }
00631 mi = rpmdbFreeIterator(mi);
00632 }
00633
00634 if (!(interfaceFlags & UNINSTALL_NODEPS)) {
00635 if (rpmdepCheck(ts, &conflicts, &numConflicts)) {
00636 numFailed = numPackages;
00637 stopUninstall = 1;
00638 }
00639
00640 if (!stopUninstall && conflicts) {
00641 rpmMessage(RPMMESS_ERROR, _("removing these packages would break "
00642 "dependencies:\n"));
00643 printDepProblems(stderr, conflicts, numConflicts);
00644 conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
00645 numFailed += numPackages;
00646 stopUninstall = 1;
00647 }
00648 }
00649
00650 if (!stopUninstall) {
00651 transFlags |= RPMTRANS_FLAG_REVERSE;
00652 numFailed += rpmRunTransactions(ts, NULL, NULL, NULL, &probs,
00653 transFlags, 0);
00654 }
00655
00656 ts = rpmtransFree(ts);
00657 (void) rpmdbClose(db);
00658
00659 return numFailed;
00660 }
00661
00662 int rpmInstallSource(const char * rootdir, const char * arg,
00663 const char ** specFile, char ** cookie)
00664 {
00665 FD_t fd;
00666 int rc;
00667
00668 fd = Fopen(arg, "r.ufdio");
00669 if (fd == NULL || Ferror(fd)) {
00670 rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
00671 if (fd) (void) Fclose(fd);
00672 return 1;
00673 }
00674
00675 if (rpmIsVerbose())
00676 fprintf(stdout, _("Installing %s\n"), arg);
00677
00678 {
00679
00680 rpmRC rpmrc = rpmInstallSourcePackage(rootdir, fd, specFile, NULL, NULL,
00681 cookie);
00682
00683 rc = (rpmrc == RPMRC_OK ? 0 : 1);
00684 }
00685 if (rc != 0) {
00686 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
00687
00688 if (specFile && *specFile)
00689 *specFile = _free(*specFile);
00690 if (cookie && *cookie)
00691 *cookie = _free(*cookie);
00692
00693 }
00694
00695 (void) Fclose(fd);
00696
00697 return rc;
00698 }
00699
00700 static int reverse = -1;
00701
00704 static int IDTintcmp(const void * a, const void * b)
00705
00706 {
00707
00708 return ( reverse * (((IDT)a)->val.i32 - ((IDT)b)->val.i32) );
00709
00710 }
00711
00712 IDTX IDTXfree(IDTX idtx)
00713 {
00714 if (idtx) {
00715 int i;
00716 if (idtx->idt)
00717 for (i = 0; i < idtx->nidt; i++) {
00718 IDT idt = idtx->idt + i;
00719 idt->h = headerFree(idt->h);
00720 idt->key = _free(idt->key);
00721 }
00722 idtx->idt = _free(idtx->idt);
00723 idtx = _free(idtx);
00724 }
00725 return NULL;
00726 }
00727
00728 IDTX IDTXnew(void)
00729 {
00730 IDTX idtx = xcalloc(1, sizeof(*idtx));
00731 idtx->delta = 10;
00732 idtx->size = sizeof(*((IDT)0));
00733 return idtx;
00734 }
00735
00736 IDTX IDTXgrow(IDTX idtx, int need)
00737 {
00738 if (need < 0) return NULL;
00739 if (idtx == NULL)
00740 idtx = IDTXnew();
00741 if (need == 0) return idtx;
00742
00743 if ((idtx->nidt + need) > idtx->alloced) {
00744 while (need > 0) {
00745 idtx->alloced += idtx->delta;
00746 need -= idtx->delta;
00747 }
00748 idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
00749 }
00750 return idtx;
00751 }
00752
00753 IDTX IDTXsort(IDTX idtx)
00754 {
00755 if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
00756 qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
00757 return idtx;
00758 }
00759
00760 IDTX IDTXload(rpmdb db, rpmTag tag)
00761 {
00762 IDTX idtx = NULL;
00763 rpmdbMatchIterator mi;
00764 HGE_t hge = (HGE_t) headerGetEntry;
00765 Header h;
00766
00767 mi = rpmdbInitIterator(db, tag, NULL, 0);
00768 while ((h = rpmdbNextIterator(mi)) != NULL) {
00769 rpmTagType type = RPM_NULL_TYPE;
00770 int_32 count = 0;
00771 int_32 * tidp;
00772
00773 tidp = NULL;
00774 if (!hge(h, tag, &type, (void **)&tidp, &count) || tidp == NULL)
00775 continue;
00776
00777 if (type == RPM_INT32_TYPE && (*tidp == 0 || *tidp == -1))
00778 continue;
00779
00780 idtx = IDTXgrow(idtx, 1);
00781 if (idtx == NULL)
00782 continue;
00783 if (idtx->idt == NULL)
00784 continue;
00785
00786 { IDT idt;
00787
00788 idt = idtx->idt + idtx->nidt;
00789
00790 idt->h = NULL;
00791 idt->key = NULL;
00792 idt->instance = rpmdbGetIteratorOffset(mi);
00793 idt->val.i32 = *tidp;
00794 }
00795 idtx->nidt++;
00796 }
00797 mi = rpmdbFreeIterator(mi);
00798
00799 return IDTXsort(idtx);
00800 }
00801
00802 IDTX IDTXglob(const char * globstr, rpmTag tag)
00803 {
00804 IDTX idtx = NULL;
00805 HGE_t hge = (HGE_t) headerGetEntry;
00806 Header h;
00807 int_32 * tidp;
00808 FD_t fd;
00809 const char ** av = NULL;
00810 int ac = 0;
00811 int rc;
00812 int i;
00813
00814 av = NULL; ac = 0;
00815 rc = rpmGlob(globstr, &ac, &av);
00816
00817 if (rc == 0)
00818 for (i = 0; i < ac; i++) {
00819 rpmTagType type;
00820 int_32 count;
00821 int isSource;
00822 rpmRC rpmrc;
00823
00824 fd = Fopen(av[i], "r.ufdio");
00825 if (fd == NULL || Ferror(fd)) {
00826 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), av[i],
00827 Fstrerror(fd));
00828 if (fd) (void) Fclose(fd);
00829 continue;
00830 }
00831
00832
00833 rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00834
00835 if (rpmrc != RPMRC_OK || isSource) {
00836 (void) Fclose(fd);
00837 continue;
00838 }
00839
00840 tidp = NULL;
00841 if (hge(h, tag, &type, (void **) &tidp, &count) && tidp) {
00842
00843 idtx = IDTXgrow(idtx, 1);
00844 if (idtx == NULL || idtx->idt == NULL) {
00845 h = headerFree(h);
00846 (void) Fclose(fd);
00847 continue;
00848 }
00849 { IDT idt;
00850 idt = idtx->idt + idtx->nidt;
00851 idt->h = headerLink(h);
00852 idt->key = av[i];
00853 av[i] = NULL;
00854 idt->instance = 0;
00855 idt->val.i32 = *tidp;
00856 }
00857 idtx->nidt++;
00858 }
00859
00860 h = headerFree(h);
00861 (void) Fclose(fd);
00862 }
00863
00864 for (i = 0; i < ac; i++)
00865 av[i] = _free(av[i]);
00866 av = _free(av); ac = 0;
00867
00868 return idtx;
00869 }
00870
00871 int rpmRollback( struct rpmInstallArguments_s * ia,
00872 const char ** argv)
00873 {
00874 rpmdb db = NULL;
00875 rpmTransactionSet ts = NULL;
00876 IDTX itids = NULL;
00877 const char * globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
00878 IDTX rtids = NULL;
00879 int rc;
00880
00881 rc = rpmdbOpen(ia->rootdir, &db, O_RDWR, 0644);
00882
00883 ts = rpmtransCreateSet(db, ia->rootdir);
00884
00885 itids = IDTXload(db, RPMTAG_INSTALLTID);
00886 rtids = IDTXglob(globstr, RPMTAG_REMOVETID);
00887
00888 globstr = _free(globstr);
00889 rtids = IDTXfree(rtids);
00890 itids = IDTXfree(itids);
00891
00892 ts = rpmtransFree(ts);
00893
00894 return 0;
00895 }