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