msm: consistency for equally ranked keys
[platform/upstream/rpm.git] / tools / rpmgraph.c
1 #include "system.h"
2 const char *__progname;
3
4 #include <rpm/rpmcli.h>
5 #include <rpm/rpmlib.h>         /* rpmReadPackageFile */
6 #include <rpm/rpmdb.h>
7 #include <rpm/rpmps.h>
8 #include <rpm/rpmte.h>
9 #include <rpm/rpmts.h>
10 #include <rpm/rpmds.h>
11
12 #include <rpm/rpmlog.h>
13 #include <rpm/rpmfileutil.h>
14
15 #include "lib/manifest.h"
16 #include "debug.h"
17
18 static int noDeps = 1;
19
20 static rpmVSFlags vsflags = 0;
21
22 static int
23 rpmGraph(rpmts ts, struct rpmInstallArguments_s * ia, const char ** fileArgv)
24 {
25     char ** pkgURL = NULL;
26     char * pkgState = NULL;
27     const char ** fnp;
28     char * fileURL = NULL;
29     int numPkgs = 0;
30     int numFailed = 0;
31     int prevx = 0;
32     int pkgx = 0;
33     char ** argv = NULL;
34     int argc = 0;
35     char ** av = NULL;
36     int ac = 0;
37     Header h;
38     rpmRC rpmrc;
39     int rc = 0;
40     rpmVSFlags ovsflags;
41     int i;
42
43     if (fileArgv == NULL)
44         return 0;
45
46     /* Build fully globbed list of arguments in argv[argc]. */
47     for (fnp = fileArgv; *fnp; fnp++) {
48         av = _free(av);
49         ac = 0;
50         rc = rpmGlob(*fnp, &ac, &av);
51         if (rc || ac == 0) continue;
52
53         argv = xrealloc(argv, (argc+2) * sizeof(*argv));
54         memcpy(argv+argc, av, ac * sizeof(*av));
55         argc += ac;
56         argv[argc] = NULL;
57     }
58     av = _free(av);     ac = 0;
59
60 restart:
61     /* Allocate sufficient storage for next set of args. */
62     if (pkgx >= numPkgs) {
63         numPkgs = pkgx + argc;
64         pkgURL = xrealloc(pkgURL, (numPkgs + 1) * sizeof(*pkgURL));
65         memset(pkgURL + pkgx, 0, ((argc + 1) * sizeof(*pkgURL)));
66         pkgState = xrealloc(pkgState, (numPkgs + 1) * sizeof(*pkgState));
67         memset(pkgState + pkgx, 0, ((argc + 1) * sizeof(*pkgState)));
68     }
69
70     /* Copy next set of args. */
71     for (i = 0; i < argc; i++) {
72         fileURL = _free(fileURL);
73         fileURL = argv[i];
74         argv[i] = NULL;
75
76         pkgURL[pkgx] = fileURL;
77         fileURL = NULL;
78         pkgx++;
79     }
80     fileURL = _free(fileURL);
81
82     /* Continue processing file arguments, building transaction set. */
83     for (fnp = (const char **) pkgURL+prevx; *fnp != NULL; fnp++, prevx++) {
84         const char * fileName;
85         FD_t fd;
86
87         (void) urlPath(*fnp, &fileName);
88
89         /* Try to read the header from a package file. */
90         fd = Fopen(*fnp, "r.ufdio");
91         if (fd == NULL || Ferror(fd)) {
92             rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *fnp,
93                         Fstrerror(fd));
94             if (fd) {
95                 Fclose(fd);
96                 fd = NULL;
97             }
98             numFailed++; *fnp = NULL;
99             continue;
100         }
101
102         /* Read the header, verifying signatures (if present). */
103         ovsflags = rpmtsSetVSFlags(ts, vsflags);
104         rpmrc = rpmReadPackageFile(ts, fd, *fnp, &h);
105         rpmtsSetVSFlags(ts, ovsflags);
106         Fclose(fd);
107         fd = NULL;
108
109         switch (rpmrc) {
110         case RPMRC_FAIL:
111         default:
112             rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), *fnp);
113             numFailed++; *fnp = NULL;
114             break;
115         case RPMRC_OK:
116             rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName, 0, NULL);
117             break;
118         case RPMRC_NOTFOUND:
119             goto maybe_manifest;
120             break;
121         }
122         h = headerFree(h); 
123         continue;
124
125 maybe_manifest:
126         /* Try to read a package manifest. */
127         fd = Fopen(*fnp, "r.ufdio");
128         if (fd == NULL || Ferror(fd)) {
129             rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *fnp,
130                         Fstrerror(fd));
131             if (fd) {
132                 Fclose(fd);
133                 fd = NULL;
134             }
135             numFailed++; *fnp = NULL;
136             break;
137         }
138
139         /* Read list of packages from manifest. */
140         rc = rpmReadPackageManifest(fd, &argc, &argv);
141         if (rc)
142             rpmlog(RPMLOG_NOTICE, _("%s: read manifest failed: %s\n"),
143                         fileURL, Fstrerror(fd));
144         Fclose(fd);
145         fd = NULL;
146
147         /* If successful, restart the query loop. */
148         if (rc == 0) {
149             prevx++;
150             goto restart;
151         }
152
153         numFailed++; *fnp = NULL;
154         break;
155     }
156
157     if (numFailed > 0) goto exit;
158
159     if (!noDeps) {
160         rpmps ps;
161         rc = rpmtsCheck(ts);
162         if (rc) {
163             numFailed += numPkgs;
164             goto exit;
165         }
166         ps = rpmtsProblems(ts);
167         if (rpmpsNumProblems(ps) > 0) {
168             rpmlog(RPMLOG_ERR, _("Failed dependencies:\n"));
169             rpmpsPrint(NULL, ps);
170             numFailed += numPkgs;
171         }
172         rpmpsFree(ps);
173     }
174
175     rc = rpmtsOrder(ts);
176     if (rc)
177         goto exit;
178
179     {   rpmtsi pi;
180         rpmte p;
181         rpmte q;
182         int oType = TR_ADDED;
183
184         fprintf(stdout, "digraph XXX {\n");
185
186         fprintf(stdout, "  rankdir=LR\n");
187
188         fprintf(stdout, "//===== Packages:\n");
189         pi = rpmtsiInit(ts);
190         while ((p = rpmtsiNext(pi, oType)) != NULL) {
191             q = rpmteParent(p);
192             if (q != NULL)
193                 fprintf(stdout, "  \"%s\" -> \"%s\"\n", rpmteN(p), rpmteN(q));
194             else {
195                 fprintf(stdout, "  \"%s\"\n", rpmteN(p));
196                 fprintf(stdout, "  { rank=max ; \"%s\" }\n", rpmteN(p));
197             }
198         }
199         rpmtsiFree(pi);
200
201         fprintf(stdout, "}\n");
202     }
203
204     rc = 0;
205
206 exit:
207     for (i = 0; i < numPkgs; i++)
208         pkgURL[i] = _free(pkgURL[i]);
209     pkgState = _free(pkgState);
210     pkgURL = _free(pkgURL);
211     argv = _free(argv);
212
213     return rc;
214 }
215
216 static struct poptOption optionsTable[] = {
217  { "check", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &noDeps, 0,
218         N_("don't verify package dependencies"), NULL },
219  { "nolegacy", '\0', POPT_BIT_SET,      &vsflags, RPMVSF_NEEDPAYLOAD,
220         N_("don't verify header+payload signature"), NULL },
221  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
222         N_("Common options for all rpm modes and executables:"),
223         NULL }, 
224
225    POPT_AUTOALIAS
226    POPT_AUTOHELP
227    POPT_TABLEEND
228 };
229
230 int
231 main(int argc, char *argv[])
232 {
233     rpmts ts = NULL;
234     struct rpmInstallArguments_s * ia = &rpmIArgs;
235     poptContext optCon;
236     int ec = 0;
237
238     optCon = rpmcliInit(argc, argv, optionsTable);
239     if (optCon == NULL)
240         exit(EXIT_FAILURE);
241
242     ts = rpmtsCreate();
243     if (rpmcliQueryFlags & VERIFY_DIGEST)
244         vsflags |= _RPMVSF_NODIGESTS;
245     if (rpmcliQueryFlags & VERIFY_SIGNATURE)
246         vsflags |= _RPMVSF_NOSIGNATURES;
247     if (rpmcliQueryFlags & VERIFY_HDRCHK)
248         vsflags |= RPMVSF_NOHDRCHK;
249     (void) rpmtsSetVSFlags(ts, vsflags);
250
251     ec = rpmGraph(ts, ia, poptGetArgs(optCon));
252
253     rpmtsFree(ts);
254
255     rpmcliFini(optCon);
256
257     return ec;
258 }