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

# tools/rpmgraph.c

Go to the documentation of this file.

    00001 #include "system.h"
    00002
    00003 #include <rpmcli.h>
    00004
    00005 #include "rpmdb.h"
    00006 #include "rpmps.h"
    00007
    00008 #include "rpmte.h"
    00009
    00010 #define _RPMTS_INTERNAL         /* ts->goal, ts->dbmode, ts->suggests */
    00011 #include "rpmts.h"
    00012
    00013 #include "manifest.h"
    00014 #include "misc.h"               /* rpmGlob */
    00015 #include "debug.h"
    00016
    00017 static int noDeps = 1;
    00018 static int noChainsaw = 0;
    00019
    00020 static rpmVSFlags vsflags = 0;
    00021
    00022 static inline /*@observer@*/ const char * const identifyDepend(int_32 f)
    00023         /*@*/
    00024 {
    00025     if (isLegacyPreReq(f))
    00026         return "PreReq:";
    00027     f = _notpre(f);
    00028     if (f & RPMSENSE_SCRIPT_PRE)
    00029         return "Requires(pre):";
    00030     if (f & RPMSENSE_SCRIPT_POST)
    00031         return "Requires(post):";
    00032     if (f & RPMSENSE_SCRIPT_PREUN)
    00033         return "Requires(preun):";
    00034     if (f & RPMSENSE_SCRIPT_POSTUN)
    00035         return "Requires(postun):";
    00036     if (f & RPMSENSE_SCRIPT_VERIFY)
    00037         return "Requires(verify):";
    00038     if (f & RPMSENSE_FIND_REQUIRES)
    00039         return "Requires(auto):";
    00040     return "Requires:";
    00041 }
    00042
    00043 static int
    00044 rpmGraph(rpmts ts, struct rpmInstallArguments_s * ia, const char ** fileArgv)
    00045         /*@*/
    00046 {
    00047     rpmps ps;
    00048     const char ** pkgURL = NULL;
    00049     char * pkgState = NULL;
    00050     const char ** fnp;
    00051     const char * fileURL = NULL;
    00052     int numPkgs = 0;
    00053     int numFailed = 0;
    00054     int prevx = 0;
    00055     int pkgx = 0;
    00056     const char ** argv = NULL;
    00057     int argc = 0;
    00058     const char ** av = NULL;
    00059     int ac = 0;
    00060     int tsflags;
    00061     Header h;
    00062     rpmRC rpmrc;
    00063     int rc = 0;
    00064     rpmVSFlags ovsflags;
    00065     int i;
    00066
    00067     if (fileArgv == NULL)
    00068         return 0;
    00069
    00070     tsflags = rpmtsFlags(ts);
    00071     if (!noChainsaw)
    00072         tsflags |= RPMTRANS_FLAG_CHAINSAW;
    00073     (void) rpmtsSetFlags(ts, tsflags);
    00074
    00075     if (ia->qva_flags & VERIFY_DIGEST)
    00076         vsflags |= _RPMVSF_NODIGESTS;
    00077     if (ia->qva_flags & VERIFY_SIGNATURE)
    00078         vsflags |= _RPMVSF_NOSIGNATURES;
    00079     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00080
    00081     /* Build fully globbed list of arguments in argv[argc]. */
    00082     for (fnp = fileArgv; *fnp; fnp++) {
    00083         av = _free(av);
    00084         ac = 0;
    00085         rc = rpmGlob(*fnp, &ac, &av);
    00086         if (rc || ac == 0) continue;
    00087
    00088         argv = xrealloc(argv, (argc+2) * sizeof(*argv));
    00089         memcpy(argv+argc, av, ac * sizeof(*av));
    00090         argc += ac;
    00091         argv[argc] = NULL;
    00092     }
    00093     av = _free(av);     ac = 0;
    00094
    00095 restart:
    00096     /* Allocate sufficient storage for next set of args. */
    00097     if (pkgx >= numPkgs) {
    00098         numPkgs = pkgx + argc;
    00099         pkgURL = xrealloc(pkgURL, (numPkgs + 1) * sizeof(*pkgURL));
    00100         memset(pkgURL + pkgx, 0, ((argc + 1) * sizeof(*pkgURL)));
    00101         pkgState = xrealloc(pkgState, (numPkgs + 1) * sizeof(*pkgState));
    00102         memset(pkgState + pkgx, 0, ((argc + 1) * sizeof(*pkgState)));
    00103     }
    00104
    00105     /* Copy next set of args. */
    00106     for (i = 0; i < argc; i++) {
    00107         fileURL = _free(fileURL);
    00108         fileURL = argv[i];
    00109         argv[i] = NULL;
    00110
    00111         pkgURL[pkgx] = fileURL;
    00112         fileURL = NULL;
    00113         pkgx++;
    00114     }
    00115     fileURL = _free(fileURL);
    00116
    00117     /* Continue processing file arguments, building transaction set. */
    00118     for (fnp = pkgURL+prevx; *fnp != NULL; fnp++, prevx++) {
    00119         const char * fileName;
    00120         FD_t fd;
    00121
    00122         (void) urlPath(*fnp, &fileName);
    00123
    00124         /* Try to read the header from a package file. */
    00125         fd = Fopen(*fnp, "r.ufdio");
    00126         if (fd == NULL || Ferror(fd)) {
    00127             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *fnp,
    00128                         Fstrerror(fd));
    00129             if (fd) {
    00130                 Fclose(fd);
    00131                 fd = NULL;
    00132             }
    00133             numFailed++; *fnp = NULL;
    00134             continue;
    00135         }
    00136
    00137         /* Read the header, verifying signatures (if present). */
    00138         ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00139         rpmrc = rpmReadPackageFile(ts, fd, *fnp, &h);
    00140         ovsflags = rpmtsSetVSFlags(ts, ovsflags);
    00141         Fclose(fd);
    00142         fd = NULL;
    00143
    00144         switch (rpmrc) {
    00145         case RPMRC_FAIL:
    00146         default:
    00147             rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *fnp);
    00148             numFailed++; *fnp = NULL;
    00149             /*@switchbreak@*/ break;
    00150         case RPMRC_OK:
    00151             rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName, 0, NULL);
    00152             /*@switchbreak@*/ break;
    00153         case RPMRC_NOTFOUND:
    00154             goto maybe_manifest;
    00155             /*@notreached@*/ /*@switchbreak@*/ break;
    00156         }
    00157         h = headerFree(h);
    00158         continue;
    00159
    00160 maybe_manifest:
    00161         /* Try to read a package manifest. */
    00162         fd = Fopen(*fnp, "r.fpio");
    00163         if (fd == NULL || Ferror(fd)) {
    00164             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *fnp,
    00165                         Fstrerror(fd));
    00166             if (fd) {
    00167                 Fclose(fd);
    00168                 fd = NULL;
    00169             }
    00170             numFailed++; *fnp = NULL;
    00171             break;
    00172         }
    00173
    00174         /* Read list of packages from manifest. */
    00175         rc = rpmReadPackageManifest(fd, &argc, &argv);
    00176         if (rc)
    00177             rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
    00178                         fileURL, Fstrerror(fd));
    00179         Fclose(fd);
    00180         fd = NULL;
    00181
    00182         /* If successful, restart the query loop. */
    00183         if (rc == 0) {
    00184             prevx++;
    00185             goto restart;
    00186         }
    00187
    00188         numFailed++; *fnp = NULL;
    00189         break;
    00190     }
    00191
    00192     if (numFailed > 0) goto exit;
    00193
    00194     if (!noDeps) {
    00195         rc = rpmtsCheck(ts);
    00196         if (rc) {
    00197             numFailed += numPkgs;
    00198             goto exit;
    00199         }
    00200         ps = rpmtsProblems(ts);
    00201         if (rpmpsNumProblems(ps) > 0) {
    00202             rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
    00203             rpmpsPrint(NULL, ps);
    00204             numFailed += numPkgs;
    00205
    00206             /*@-branchstate@*/
    00207             if (ts->suggests != NULL && ts->nsuggests > 0) {
    00208                 rpmMessage(RPMMESS_NORMAL, _("    Suggested resolutions:\n"));
    00209                 for (i = 0; i < ts->nsuggests; i++) {
    00210                     const char * str = ts->suggests[i];
    00211
    00212                     if (str == NULL)
    00213                         break;
    00214
    00215                     rpmMessage(RPMMESS_NORMAL, "\t%s\n", str);
    00216                     ts->suggests[i] = NULL;
    00217                     str = _free(str);
    00218                 }
    00219                 ts->suggests = _free(ts->suggests);
    00220             }
    00221             /*@=branchstate@*/
    00222         }
    00223         ps = rpmpsFree(ps);
    00224     }
    00225
    00226     if (numFailed > 0) goto exit;
    00227
    00228     rc = rpmtsOrder(ts);
    00229     if (rc)
    00230         goto exit;
    00231
    00232     {   rpmtsi pi;
    00233         rpmte p;
    00234         rpmte q;
    00235         unsigned char * selected =
    00236                         alloca(sizeof(*selected) * (rpmtsNElements(ts) + 1));
    00237         int oType = TR_ADDED;
    00238
    00239         fprintf(stdout, "digraph XXX {\n");
    00240
    00241         fprintf(stdout, "  rankdir=LR\n");
    00242
    00243         fprintf(stdout, "//===== Packages:\n");
    00244         pi = rpmtsiInit(ts);
    00245         while ((p = rpmtsiNext(pi, oType)) != NULL) {
    00246             fprintf(stdout, "//%5d%5d %s\n", rpmteTree(p), rpmteDepth(p), rpmteN(p));
    00247             q = rpmteParent(p);
    00248             if (q != NULL)
    00249                 fprintf(stdout, "  \"%s\" -> \"%s\"\n", rpmteN(p), rpmteN(q));
    00250             else {
    00251                 fprintf(stdout, "  \"%s\"\n", rpmteN(p));
    00252                 fprintf(stdout, "  { rank=max ; \"%s\" }\n", rpmteN(p));
    00253             }
    00254         }
    00255         pi = rpmtsiFree(pi);
    00256
    00257         fprintf(stdout, "}\n");
    00258     }
    00259
    00260     rc = 0;
    00261
    00262 exit:
    00263     for (i = 0; i < numPkgs; i++)
    00264         pkgURL[i] = _free(pkgURL[i]);
    00265     pkgState = _free(pkgState);
    00266     pkgURL = _free(pkgURL);
    00267     argv = _free(argv);
    00268
    00269     return rc;
    00270 }
    00271
    00272 static struct poptOption optionsTable[] = {
    00273  { "check", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &noDeps, 0,
    00274         N_("don't verify package dependencies"), NULL },
    00275  { "nolegacy", '\0', POPT_BIT_SET,      &vsflags, RPMVSF_NEEDPAYLOAD,
    00276         N_("don't verify header+payload signature"), NULL },
    00277
    00278  { "nochainsaw", '\0', POPT_ARGFLAG_DOC_HIDDEN, &noChainsaw, 0,
    00279         NULL, NULL},
    00280
    00281  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
    00282         N_("Common options for all rpm modes and executables:"),
    00283         NULL },
    00284
    00285    POPT_AUTOALIAS
    00286    POPT_AUTOHELP
    00287    POPT_TABLEEND
    00288 };
    00289
    00290 int
    00291 main(int argc, char *const argv[])
    00292 {
    00293     rpmts ts = NULL;
    00294     struct rpmInstallArguments_s * ia = &rpmIArgs;
    00295     poptContext optCon;
    00296     int ec = 0;
    00297
    00298     optCon = rpmcliInit(argc, argv, optionsTable);
    00299     if (optCon == NULL)
    00300         exit(EXIT_FAILURE);
    00301
    00302     ts = rpmtsCreate();
    00303     if (rpmcliQueryFlags & VERIFY_DIGEST)
    00304         vsflags |= _RPMVSF_NODIGESTS;
    00305     if (rpmcliQueryFlags & VERIFY_SIGNATURE)
    00306         vsflags |= _RPMVSF_NOSIGNATURES;
    00307     if (rpmcliQueryFlags & VERIFY_HDRCHK)
    00308         vsflags |= RPMVSF_NOHDRCHK;
    00309     (void) rpmtsSetVSFlags(ts, vsflags);
    00310
    00311     ec = rpmGraph(ts, ia, poptGetArgs(optCon));
    00312
    00313     ts = rpmtsFree(ts);
    00314
    00315     optCon = rpmcliFini(optCon);
    00316
    00317     return ec;
    00318 }