Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

lib/rpminstall.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmlib.h>
00008 #include <rpmmacro.h>
00009 #include <rpmurl.h>
00010 
00011 #include "manifest.h"
00012 #include "misc.h"
00013 #include "debug.h"
00014 
00015 /*@access rpmTransactionSet@*/  /* XXX compared with NULL */
00016 /*@access Header@*/             /* XXX compared with NULL */
00017 /*@access FD_t@*/               /* XXX compared with NULL */
00018 
00024 static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) {
00025     if (this)   free((void *)this);
00026     return NULL;
00027 }
00028 
00029 /* Define if you want percentage progress in the hash bars when
00030  * writing to a tty (ordinary hash bars otherwise) --claudio
00031  */
00032 #define FANCY_HASH
00033 
00034 static int hashesPrinted = 0;
00035 
00036 #ifdef FANCY_HASH
00037 static int packagesTotal = 0;
00038 static int progressTotal = 0;
00039 static int progressCurrent = 0;
00040 #endif
00041 
00044 static void printHash(const unsigned long amount, const unsigned long total)
00045 {
00046     int hashesNeeded;
00047     int hashesTotal = 50;
00048 
00049 #ifdef FANCY_HASH
00050     if (isatty (STDOUT_FILENO))
00051         hashesTotal = 44;
00052 #endif
00053 
00054     if (hashesPrinted != hashesTotal) {
00055         hashesNeeded = hashesTotal * (total ? (((float) amount) / total) : 1);
00056         while (hashesNeeded > hashesPrinted) {
00057 #ifdef FANCY_HASH
00058             if (isatty (STDOUT_FILENO)) {
00059                 int i;
00060                 for (i = 0; i < hashesPrinted; i++) putchar ('#');
00061                 for (; i < hashesTotal; i++) putchar (' ');
00062                 printf ("(%3d%%)",
00063                         (int)(100 * (total ? (((float) amount) / total) : 1)));
00064                 for (i = 0; i < (hashesTotal + 6); i++) putchar ('\b');
00065             } else
00066 #endif
00067             fprintf(stdout, "#");
00068 
00069             hashesPrinted++;
00070         }
00071         fflush(stdout);
00072         hashesPrinted = hashesNeeded;
00073 
00074         if (hashesPrinted == hashesTotal) {
00075 #ifdef FANCY_HASH
00076             int i;
00077             progressCurrent++;
00078             for (i = 1; i < hashesPrinted; i++) putchar ('#');
00079             printf (" [%3d%%]\n", (int)(100 * (progressTotal ?
00080                         (((float) progressCurrent) / progressTotal) : 1)));
00081 #else
00082             fprintf (stdout, "\n");
00083 #endif
00084         }
00085         fflush(stdout);
00086     }
00087 }
00088 
00091 static void * showProgress(const void * arg, const rpmCallbackType what,
00092                            const unsigned long amount,
00093                            const unsigned long total,
00094                            const void * pkgKey, void * data)
00095 {
00096     Header h = (Header) arg;
00097     char * s;
00098     int flags = (int) ((long)data);
00099     void * rc = NULL;
00100     const char * filename = pkgKey;
00101     static FD_t fd;
00102 
00103     switch (what) {
00104     case RPMCALLBACK_INST_OPEN_FILE:
00105         fd = Fopen(filename, "r.ufdio");
00106         if (fd)
00107             fd = fdLink(fd, "persist (showProgress)");
00108         return fd;
00109         /*@notreached@*/ break;
00110 
00111     case RPMCALLBACK_INST_CLOSE_FILE:
00112         fd = fdFree(fd, "persist (showProgress)");
00113         if (fd) {
00114             Fclose(fd);
00115             fd = NULL;
00116         }
00117         break;
00118 
00119     case RPMCALLBACK_INST_START:
00120         hashesPrinted = 0;
00121         if (!(flags & INSTALL_LABEL))
00122             break;
00123         if (flags & INSTALL_HASH) {
00124             s = headerSprintf(h, "%{NAME}", rpmTagTable, rpmHeaderFormats,NULL);
00125 #ifdef FANCY_HASH
00126             if (isatty (STDOUT_FILENO))
00127                 fprintf(stdout, "%4d:%-23.23s", progressCurrent + 1, s);
00128             else
00129 #else
00130                 fprintf(stdout, "%-28s", s);
00131 #endif
00132             fflush(stdout);
00133         } else {
00134             s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
00135                                   rpmTagTable, rpmHeaderFormats, NULL);
00136             fprintf(stdout, "%s\n", s);
00137             fflush(stdout);
00138         }
00139         s = _free(s);
00140         break;
00141 
00142     case RPMCALLBACK_TRANS_PROGRESS:
00143     case RPMCALLBACK_INST_PROGRESS:
00144         if (flags & INSTALL_PERCENT)
00145             fprintf(stdout, "%%%% %f\n", (total
00146                                 ? ((float) ((((float) amount) / total) * 100))
00147                                 : 100.0));
00148         else if (flags & INSTALL_HASH)
00149             printHash(amount, total);
00150         fflush(stdout);
00151         break;
00152 
00153     case RPMCALLBACK_TRANS_START:
00154         hashesPrinted = 0;
00155 #ifdef FANCY_HASH
00156         progressTotal = 1;
00157         progressCurrent = 0;
00158 #endif
00159         if (!(flags & INSTALL_LABEL))
00160             break;
00161         if (flags & INSTALL_HASH)
00162             fprintf(stdout, "%-28s", _("Preparing..."));
00163         else
00164             printf("%s\n", _("Preparing packages for installation..."));
00165         fflush(stdout);
00166         break;
00167 
00168     case RPMCALLBACK_TRANS_STOP:
00169         if (flags & INSTALL_HASH)
00170             printHash(1, 1);    /* Fixes "preparing..." progress bar */
00171 #ifdef FANCY_HASH
00172         progressTotal = packagesTotal;
00173         progressCurrent = 0;
00174 #endif
00175         break;
00176 
00177     case RPMCALLBACK_UNINST_PROGRESS:
00178     case RPMCALLBACK_UNINST_START:
00179     case RPMCALLBACK_UNINST_STOP:
00180         /* ignore */
00181         break;
00182     }
00183 
00184     return rc;
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     rpmTransactionSet ts = NULL;
00195     int notifyFlags = interfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
00196     rpmdb db = NULL;
00197     const char ** pkgURL = NULL;
00198     char * pkgState = NULL;
00199     const char ** fnp;
00200     const char * fileURL = NULL;
00201     int numPkgs = 0;
00202     int numRPMS = 0;
00203     int numSRPMS = 0;
00204     int numFailed = 0;
00205     int stopInstall = 0;
00206     int dbIsOpen = 0;
00207     rpmRelocation * defaultReloc = relocations;
00208     const char ** sourceURL = NULL;
00209     int prevx;
00210     int pkgx;
00211     const char ** argv = NULL;
00212     int argc = 0;
00213     const char ** av = NULL;
00214     int ac = 0;
00215     Header h;
00216     FD_t fd;
00217     int rc;
00218     int i;
00219 
00220     while (defaultReloc && defaultReloc->oldPath)
00221         defaultReloc++;
00222     if (defaultReloc && !defaultReloc->newPath) defaultReloc = NULL;
00223 
00224     /* Build fully globbed list of arguments in argv[argc]. */
00225     for (fnp = fileArgv; *fnp; fnp++) {
00226         av = _free(av);
00227         ac = 0;
00228         rc = rpmGlob(*fnp, &ac, &av);
00229         if (rc || ac == 0) continue;
00230 
00231         if (argc == 0)
00232             argv = xmalloc((argc+2) * sizeof(*argv));
00233         else
00234             argv = xrealloc(argv, (argc+2) * sizeof(*argv));
00235         memcpy(argv+argc, av, ac * sizeof(*av));
00236         argc += ac;
00237         argv[argc] = NULL;
00238     }
00239     av = _free(av);
00240 
00241     numPkgs = 0;
00242     prevx = 0;
00243     pkgx = 0;
00244 
00245 restart:
00246     /* Allocate sufficient storage for next set of args. */
00247     if (pkgx >= numPkgs) {
00248         numPkgs = pkgx + argc;
00249         pkgURL = (pkgURL == NULL)
00250             ? xmalloc( (numPkgs + 1) * sizeof(*pkgURL))
00251             : xrealloc(pkgURL, (numPkgs + 1) * sizeof(*pkgURL));
00252         memset(pkgURL + pkgx, 0, ((argc + 1) * sizeof(*pkgURL)));
00253         pkgState = (pkgState == NULL)
00254             ? xmalloc( (numPkgs + 1) * sizeof(*pkgState))
00255             : xrealloc(pkgState, (numPkgs + 1) * sizeof(*pkgState));
00256         memset(pkgState + pkgx, 0, ((argc + 1) * sizeof(*pkgState)));
00257     }
00258 
00259     /* Retrieve next set of args, cache on local storage. */
00260     for (i = 0; i < argc; i++) {
00261         fileURL = _free(fileURL);
00262         fileURL = argv[i];
00263         argv[i] = NULL;
00264 
00265         switch (urlIsURL(fileURL)) {
00266         case URL_IS_FTP:
00267         case URL_IS_HTTP:
00268         {   const char *tfn;
00269 
00270             if (rpmIsVerbose())
00271                 fprintf(stdout, _("Retrieving %s\n"), fileURL);
00272 
00273             {   char tfnbuf[64];
00274                 strcpy(tfnbuf, "rpm-xfer.XXXXXX");
00275                 /*@-unrecog@*/ mktemp(tfnbuf) /*@=unrecog@*/;
00276                 tfn = rpmGenPath(rootdir, "%{_tmppath}/", tfnbuf);
00277             }
00278 
00279             /* XXX undefined %{name}/%{version}/%{release} here */
00280             /* XXX %{_tmpdir} does not exist */
00281             rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
00282             rc = urlGetFile(fileURL, tfn);
00283             if (rc < 0) {
00284                 rpmMessage(RPMMESS_ERROR,
00285                         _("skipping %s - transfer failed - %s\n"),
00286                         fileURL, ftpStrerror(rc));
00287                 numFailed++;
00288                 pkgURL[pkgx] = NULL;
00289                 tfn = _free(tfn);
00290                 break;
00291             }
00292             pkgState[pkgx] = 1;
00293             pkgURL[pkgx] = tfn;
00294             pkgx++;
00295         }   break;
00296         case URL_IS_PATH:
00297         default:
00298             pkgURL[pkgx] = fileURL;
00299             fileURL = NULL;
00300             pkgx++;
00301             break;
00302         }
00303     }
00304     fileURL = _free(fileURL);
00305 
00306     if (numFailed) goto exit;
00307 
00308     /* Continue processing file arguments, building transaction set. */
00309     for (fnp = pkgURL+prevx; *fnp; fnp++, prevx++) {
00310         const char * fileName;
00311         rpmRC rpmrc;
00312         int isSource;
00313 
00314         rpmMessage(RPMMESS_DEBUG, "============== %s\n", *fnp);
00315         (void) urlPath(*fnp, &fileName);
00316 
00317         /* Try to read the header from a package file. */
00318         fd = Fopen(*fnp, "r.ufdio");
00319         if (fd == NULL || Ferror(fd)) {
00320             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *fnp,
00321                         Fstrerror(fd));
00322             if (fd) Fclose(fd);
00323             numFailed++; *fnp = NULL;
00324             continue;
00325         }
00326 
00327         rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00328         Fclose(fd);
00329 
00330         if (rpmrc == RPMRC_FAIL || rpmrc == RPMRC_SHORTREAD) {
00331             numFailed++; *fnp = NULL;
00332             continue;
00333         }
00334         if ((rpmrc == RPMRC_OK || rpmrc == RPMRC_BADSIZE) && isSource) {
00335             rpmMessage(RPMMESS_DEBUG, "\tadded source rpm[%d]\n", numSRPMS);
00336                 sourceURL = (sourceURL == NULL)
00337                     ? xmalloc( (numSRPMS + 2) * sizeof(*sourceURL))
00338                     : xrealloc(sourceURL, (numSRPMS + 2) * sizeof(*sourceURL));
00339             sourceURL[numSRPMS++] = *fnp;
00340             *fnp = NULL;
00341             continue;
00342         }
00343         if (rpmrc == RPMRC_OK || rpmrc == RPMRC_BADSIZE) {
00344             if (!dbIsOpen) {
00345                 int mode = (transFlags & RPMTRANS_FLAG_TEST)
00346                                 ? O_RDONLY : (O_RDWR | O_CREAT);
00347 
00348                 if (rpmdbOpen(rootdir, &db, mode, 0644)) {
00349                     const char *dn;
00350                     dn = rpmGetPath( (rootdir ? rootdir : ""),
00351                                         "%{_dbpath}", NULL);
00352                     rpmMessage(RPMMESS_ERROR,
00353                                 _("cannot open Packages database in %s\n"), dn);
00354                     dn = _free(dn);
00355                     numFailed++; *fnp = NULL;
00356                     break;
00357                 }
00358                 ts = rpmtransCreateSet(db, rootdir);
00359                 dbIsOpen = 1;
00360             }
00361 
00362             if (defaultReloc) {
00363                 const char ** paths;
00364                 int pft;
00365                 int c;
00366 
00367                 if (headerGetEntry(h, RPMTAG_PREFIXES, &pft,
00368                                        (void **) &paths, &c) && (c == 1)) {
00369                     defaultReloc->oldPath = xstrdup(paths[0]);
00370                     paths = headerFreeData(paths, pft);
00371                 } else {
00372                     const char * name;
00373                     headerNVR(h, &name, NULL, NULL);
00374                     rpmMessage(RPMMESS_ERROR,
00375                                _("package %s is not relocateable\n"), name);
00376                     numFailed++;
00377                     goto exit;
00378                     /*@notreached@*/
00379                 }
00380             }
00381 
00382             /* On --freshen, verify package is installed and newer */
00383             if (interfaceFlags & INSTALL_FRESHEN) {
00384                 rpmdbMatchIterator mi;
00385                 const char * name;
00386                 Header oldH;
00387                 int count;
00388 
00389                 headerNVR(h, &name, NULL, NULL);
00390                 mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00391                 count = rpmdbGetIteratorCount(mi);
00392                 while ((oldH = rpmdbNextIterator(mi)) != NULL) {
00393                     if (rpmVersionCompare(oldH, h) < 0)
00394                         continue;
00395                     /* same or newer package already installed */
00396                     count = 0;
00397                     break;
00398                 }
00399                 rpmdbFreeIterator(mi);
00400                 if (count == 0) {
00401                     headerFree(h);
00402                     continue;
00403                     break;      /* XXX out of switch */
00404                 }
00405                 /* Package is newer than those currently installed. */
00406             }
00407 
00408             rc = rpmtransAddPackage(ts, h, NULL, fileName,
00409                                (interfaceFlags & INSTALL_UPGRADE) != 0,
00410                                relocations);
00411             headerFree(h);      /* XXX reference held by transaction set */
00412             if (defaultReloc)
00413                 defaultReloc->oldPath = _free(defaultReloc->oldPath);
00414 
00415             switch(rc) {
00416             case 0:
00417                 rpmMessage(RPMMESS_DEBUG, "\tadded binary rpm[%d]\n", numRPMS);
00418                 break;
00419             case 1:
00420                 rpmMessage(RPMMESS_ERROR,
00421                             _("error reading from file %s\n"), *fnp);
00422                 numFailed++;
00423                 goto exit;
00424                 /*@notreached@*/ break;
00425             case 2:
00426                 rpmMessage(RPMMESS_ERROR,
00427                             _("file %s requires a newer version of RPM\n"),
00428                             *fnp);
00429                 numFailed++;
00430                 goto exit;
00431                 /*@notreached@*/ break;
00432             }
00433 
00434             numRPMS++;
00435             continue;
00436         }
00437 
00438         if (rpmrc != RPMRC_BADMAGIC) {
00439             rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *fnp);
00440             numFailed++; *fnp = NULL;
00441             break;
00442         }
00443 
00444         /* Try to read a package manifest. */
00445         fd = Fopen(*fnp, "r.fpio");
00446         if (fd == NULL || Ferror(fd)) {
00447             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *fnp,
00448                         Fstrerror(fd));
00449             if (fd) Fclose(fd);
00450             numFailed++; *fnp = NULL;
00451             break;
00452         }
00453 
00454         /* Read list of packages from manifest. */
00455         rc = rpmReadPackageManifest(fd, &argc, &argv);
00456         if (rc)
00457             rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00458                         fileURL, Fstrerror(fd));
00459         Fclose(fd);
00460 
00461         /* If successful, restart the query loop. */
00462         if (rc == 0) {
00463             prevx++;
00464             goto restart;
00465         }
00466 
00467         numFailed++; *fnp = NULL;
00468         break;
00469     }
00470 
00471     rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"),
00472                 numSRPMS, numRPMS);
00473 
00474     if (numFailed) goto exit;
00475 
00476     if (numRPMS && !(interfaceFlags & INSTALL_NODEPS)) {
00477         struct rpmDependencyConflict * conflicts;
00478         int numConflicts;
00479 
00480         if (rpmdepCheck(ts, &conflicts, &numConflicts)) {
00481             numFailed = numPkgs;
00482             stopInstall = 1;
00483         }
00484 
00485         if (!stopInstall && conflicts) {
00486             rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
00487             printDepProblems(stderr, conflicts, numConflicts);
00488             rpmdepFreeConflicts(conflicts, numConflicts);
00489             numFailed = numPkgs;
00490             stopInstall = 1;
00491         }
00492     }
00493 
00494     if (numRPMS && !(interfaceFlags & INSTALL_NOORDER)) {
00495         if (rpmdepOrder(ts)) {
00496             numFailed = numPkgs;
00497             stopInstall = 1;
00498         }
00499     }
00500 
00501     if (numRPMS && !stopInstall) {
00502         rpmProblemSet probs = NULL;
00503 
00504 #ifdef FANCY_HASH
00505         packagesTotal = numRPMS;
00506 #endif
00507         rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n"));
00508         rc = rpmRunTransactions(ts, showProgress, (void *) ((long)notifyFlags),
00509                                     NULL, &probs, transFlags, probFilter);
00510 
00511         if (rc < 0) {
00512             numFailed += numRPMS;
00513         } else if (rc > 0) {
00514             numFailed += rc;
00515             rpmProblemSetPrint(stderr, probs);
00516         }
00517 
00518         if (probs) rpmProblemSetFree(probs);
00519     }
00520 
00521     if (numSRPMS && !stopInstall) {
00522         for (i = 0; i < numSRPMS; i++) {
00523             fd = Fopen(sourceURL[i], "r.ufdio");
00524             if (fd == NULL || Ferror(fd)) {
00525                 rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
00526                            sourceURL[i], Fstrerror(fd));
00527                 if (fd) Fclose(fd);
00528                 continue;
00529             }
00530 
00531             if (!(transFlags & RPMTRANS_FLAG_TEST)) {
00532                 rpmRC rpmrc = rpmInstallSourcePackage(rootdir, fd, NULL,
00533                         showProgress, (void *) ((long)notifyFlags), NULL);
00534                 if (rpmrc != RPMRC_OK) numFailed++;
00535             }
00536 
00537             Fclose(fd);
00538         }
00539     }
00540 
00541 exit:
00542     if (ts) rpmtransFree(ts);
00543     for (i = 0; i < numPkgs; i++) {
00544         if (pkgState[i] == 1)
00545             Unlink(pkgURL[i]);
00546         pkgURL[i] = _free(pkgURL[i]);
00547     }
00548     pkgState = _free(pkgState);
00549     pkgURL = _free(pkgURL);
00550     argv = _free(argv);
00551     if (dbIsOpen) rpmdbClose(db);
00552     return numFailed;
00553 }
00554 
00555 int rpmErase(const char * rootdir, const char ** argv,
00556                 rpmtransFlags transFlags,
00557                 rpmEraseInterfaceFlags interfaceFlags)
00558 {
00559     rpmdb db;
00560     int mode;
00561     int count;
00562     const char ** arg;
00563     int numFailed = 0;
00564     rpmTransactionSet ts;
00565     struct rpmDependencyConflict * conflicts;
00566     int numConflicts;
00567     int stopUninstall = 0;
00568     int numPackages = 0;
00569     rpmProblemSet probs;
00570 
00571     if (transFlags & RPMTRANS_FLAG_TEST)
00572         mode = O_RDONLY;
00573     else
00574         mode = O_RDWR | O_EXCL;
00575         
00576     if (rpmdbOpen(rootdir, &db, mode, 0644)) {
00577         const char *dn;
00578         dn = rpmGetPath( (rootdir ? rootdir : ""), "%{_dbpath}", NULL);
00579         rpmMessage(RPMMESS_ERROR, _("cannot open %s/packages.rpm\n"), dn);
00580         dn = _free(dn);
00581         return -1;
00582     }
00583 
00584     ts = rpmtransCreateSet(db, rootdir);
00585     for (arg = argv; *arg; arg++) {
00586         rpmdbMatchIterator mi;
00587 
00588         /* XXX HACK to get rpmdbFindByLabel out of the API */
00589         mi = rpmdbInitIterator(db, RPMDBI_LABEL, *arg, 0);
00590         count = rpmdbGetIteratorCount(mi);
00591         if (count <= 0) {
00592             rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
00593             numFailed++;
00594         } else if (!(count == 1 || (interfaceFlags & UNINSTALL_ALLMATCHES))) {
00595             rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
00596                         *arg);
00597             numFailed++;
00598         } else {
00599             Header h;   /* XXX iterator owns the reference */
00600             while ((h = rpmdbNextIterator(mi)) != NULL) {
00601                 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
00602                 if (recOffset) {
00603                     rpmtransRemovePackage(ts, recOffset);
00604                     numPackages++;
00605                 }
00606             }
00607         }
00608         rpmdbFreeIterator(mi);
00609     }
00610 
00611     if (!(interfaceFlags & UNINSTALL_NODEPS)) {
00612         if (rpmdepCheck(ts, &conflicts, &numConflicts)) {
00613             numFailed = numPackages;
00614             stopUninstall = 1;
00615         }
00616 
00617         if (!stopUninstall && conflicts) {
00618             rpmMessage(RPMMESS_ERROR, _("removing these packages would break "
00619                               "dependencies:\n"));
00620             printDepProblems(stderr, conflicts, numConflicts);
00621             rpmdepFreeConflicts(conflicts, numConflicts);
00622             numFailed += numPackages;
00623             stopUninstall = 1;
00624         }
00625     }
00626 
00627     if (!stopUninstall) {
00628         transFlags |= RPMTRANS_FLAG_REVERSE;
00629         numFailed += rpmRunTransactions(ts, NULL, NULL, NULL, &probs,
00630                                         transFlags, 0);
00631     }
00632 
00633     rpmtransFree(ts);
00634     rpmdbClose(db);
00635 
00636     return numFailed;
00637 }
00638 
00639 int rpmInstallSource(const char * rootdir, const char * arg,
00640                 const char ** specFile, char ** cookie)
00641 {
00642     FD_t fd;
00643     int rc;
00644 
00645     fd = Fopen(arg, "r.ufdio");
00646     if (fd == NULL || Ferror(fd)) {
00647         rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
00648         if (fd) Fclose(fd);
00649         return 1;
00650     }
00651 
00652     if (rpmIsVerbose())
00653         fprintf(stdout, _("Installing %s\n"), arg);
00654 
00655     {   rpmRC rpmrc = rpmInstallSourcePackage(rootdir, fd, specFile, NULL, NULL,
00656                                  cookie);
00657         rc = (rpmrc == RPMRC_OK ? 0 : 1);
00658     }
00659     if (rc != 0) {
00660         rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
00661         if (specFile && *specFile)
00662             *specFile = _free(*specFile);
00663         if (cookie && *cookie)
00664             *cookie = _free(*cookie);
00665     }
00666 
00667     Fclose(fd);
00668 
00669     return rc;
00670 }

Generated at Thu Apr 19 15:29:43 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001