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