rpm  4.5
rpmdeps.c
Go to the documentation of this file.
1 #include "system.h"
2 const char *__progname;
3 
4 #include <rpmcli.h>
5 #include <argv.h>
6 #include <rpmds.h>
7 #include <stringbuf.h>
8 #define _RPMFC_INTERNAL /* XXX for debugging */
9 #include <rpmfc.h>
10 
11 #include "debug.h"
12 
13 /*@unchecked@*/
14 char *progname;
15 
16 #define RPMDEP_RPMFC 1
17 #define RPMDEP_RPMDSCPUINFO 2
18 #define RPMDEP_RPMDSRPMLIB 3
19 #define RPMDEP_RPMDSSYSINFO 4
20 #define RPMDEP_RPMDSGETCONF 5
21 #define RPMDEP_RPMDSELF 6
22 #define RPMDEP_RPMDSLDCONFIG 7
23 #define RPMDEP_RPMDSUNAME 8
24 #define RPMDEP_RPMDSPIPE 9
25 
26 #define RPMDEP_RPMDSPERL 10
27 #define RPMDEP_RPMDSPYTHON 11
28 #define RPMDEP_RPMDSLIBTOOL 12
29 #define RPMDEP_RPMDSPKGCONFIG 13
30 
31 #define RPMDEP_RPMDSPUBKEY 14
32 #define RPMDEP_RPMDSARCH 15
33 #define RPMDEP_RPMDSFILE 16
34 #define RPMDEP_RPMDSSONAME 17
35 #define RPMDEP_RPMDSPACKAGE 18
36 
37 #define RPMDEP_RPMDSJAVA 20
38 #define RPMDEP_RPMDSRUBY 21
39 #define RPMDEP_RPMDSPHP 22
40 
41 #define RPMDEP_RPMDSDPKGRPM 32
42 #define RPMDEP_RPMDSRPMDPKG 33
43 
44 /*@unchecked@*/
46 
47 /*@unchecked@*/
48 static int print_provides = 1;
49 
50 /*@unchecked@*/
51 static int print_requires = 1;
52 
53 /*@unchecked@*/
54 static int print_closure = 0;
55 
56 #define _PERL_PROVIDES "/usr/bin/find /usr/lib/perl5 | /usr/lib/rpm/perl.prov"
57 /*@unchecked@*/ /*@observer@*/
58 static const char * _perl_provides = _PERL_PROVIDES;
59 
60 #define _PERL_REQUIRES "rpm -qa --fileclass | grep 'perl script' | sed -e 's/\t.*$//' | /usr/lib/rpm/perl.req"
61 /*@unchecked@*/ /*@observer@*/
62 static const char * _perl_requires = _PERL_REQUIRES;
63 
64 #define _JAVA_PROVIDES "rpm -qal | egrep '\\.(jar|class)$' | /usr/lib/rpm/javadeps.sh -P"
65 /*@unchecked@*/ /*@observer@*/
66 static const char * _java_provides = _JAVA_PROVIDES;
67 
68 #define _JAVA_REQUIRES "rpm -qal | egrep '\\.(jar|class)$' | /usr/lib/rpm/javadeps.sh -R"
69 /*@unchecked@*/ /*@observer@*/
70 static const char * _java_requires = _JAVA_REQUIRES;
71 
72 #define _LIBTOOL_PROVIDES "/usr/bin/find /usr/lib -name '*.la' | /usr/lib/rpm/libtooldeps.sh -P /"
73 /*@unchecked@*/ /*@observer@*/
74 static const char * _libtool_provides = _LIBTOOL_PROVIDES;
75 
76 #define _LIBTOOL_REQUIRES "/bin/rpm -qal | grep '\\.la$' | /usr/lib/rpm/libtooldeps.sh -R /"
77 /*@unchecked@*/ /*@observer@*/
78 static const char * _libtool_requires = _LIBTOOL_REQUIRES;
79 
80 #define _PKGCONFIG_PROVIDES "/usr/bin/find /usr/lib -name '*.pc' | /usr/lib/rpm/pkgconfigdeps.sh -P"
82 
83 #define _PKGCONFIG_REQUIRES "/bin/rpm -qal | grep '\\.pc$' | /usr/lib/rpm/pkgconfigdeps.sh -R"
85 
86 #define _DPKG_PROVIDES "egrep '^(Package|Status|Version|Provides):' /var/lib/dpkg/status | sed -e '\n\
87 /^Package: / {\n\
88  N\n\
89  /not-installed/d\n\
90  N\n\
91  s|^Package: \\([^\\n]*\\)\\n[^\\n]*\\nVersion: \\(.*\\)$|\\1 = \\2|\n\
92 }\n\
93 /^Provides: / {\n\
94  s|^Provides: ||\n\
95  s|, |\\n|g\n\
96 }' | sed -f /usr/lib/rpm/dpkg2fc.sed | sort -u | tee /tmp/dpkg"
97 static const char * _dpkg_provides = _DPKG_PROVIDES;
98 
99 #define _DPKG_REQUIRES "egrep '^(Package|Status|Pre-Depends|Depends):' /var/lib/dpkg/status | sed -e '\n\
100 /^Package: / {\n\
101  N\n\
102  /not-installed/d\n\
103  s|^Package: [^\\n]*\\n.*$||\n\
104 }\n\
105 /^Depends: / {\n\
106  s|^Depends: ||\n\
107  s|(\\([^)]*\\))|\\1|g\n\
108  s|>>|>|\n\
109  s|<<|<|\n\
110  s|, |\\n|g\n\
111 }\n\
112 /^Pre-Depends: / {\n\
113  s|^Pre-Depends: ||\n\
114  s|(\\([^)]*\\))|\\1|g\n\
115  s|>>|>|\n\
116  s|<<|<|\n\
117  s|, |\\n|g\n\
118 }' | sed -f /usr/lib/rpm/dpkg2fc.sed | sed -e 's/ |.*$//' | sort -u | tee /tmp/dpkg"
119 static const char * _dpkg_requires = _DPKG_REQUIRES;
120 
121 #define _RPMDB_PACKAGE_PROVIDES "/bin/rpm -qa --qf '%{name} = %|epoch?{%{epoch}:}|%{version}-%{release}\n' | sort -u"
123 
124 #define _RPMDB_PACKAGE_REQUIRES "/bin/rpm -qa --requires | sort -u | sed -e '/^\\//d' -e '/.*\\.so.*/d' -e '/^%/d' -e '/^.*(.*)/d'"
126 
127 #define _RPMDB_SONAME_REQUIRES "/bin/rpm -qa --requires | grep -v '^/' | grep '.*\\.so.*' | sort -u"
129 
130 #define _RPMDB_FILE_REQUIRES "/bin/rpm -qa --requires | grep '^/' | sort -u"
132 
133 static int rpmdepPrint(const char * msg, rpmds ds, FILE * fp)
134 {
135  if (fp == NULL) fp = stderr;
136 
137  if (msg)
138  fprintf(fp, "===================================== %s\n", msg);
139 
140  ds = rpmdsInit(ds);
141  while (rpmdsNext(ds) >= 0) {
142  if (_rpmfc_debug || rpmIsDebug())
143  fprintf(fp, "%6d\t", rpmdsIx(ds));
144  if (_rpmfc_debug || rpmIsVerbose())
145  fprintf(fp, "%s: ", rpmdsTagName(ds));
146  fprintf(fp, "%s\n", rpmdsDNEVR(ds)+2);
147  }
148  return 0;
149 }
150 
151 static struct poptOption optionsTable[] = {
152 
153  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
154  N_("Common options for all rpm modes and executables:"),
155  NULL },
156 
157  { "cpuinfo", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSCPUINFO,
158  N_("print cpuinfo(...) dependency set"), NULL },
159  { "rpmlib", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSRPMLIB,
160  N_("print rpmlib(...) dependency set"), NULL },
161  { "sysinfo", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSSYSINFO,
162  N_("print /etc/rpm/sysinfo dependency set"), NULL },
163  { "getconf", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSGETCONF,
164  N_("print getconf(...) dependency set"), NULL },
165  { "elf", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSELF,
166  N_("print soname(...) dependencies for elf files"), NULL },
167  { "ldconfig", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSLDCONFIG,
168  N_("print soname(...) dependencies from /etc/ld.so.cache"), NULL },
169  { "uname", 0, POPT_ARG_VAL, &rpmdeps_mode, RPMDEP_RPMDSUNAME,
170  N_("print uname(...) dependency set"), NULL },
171  { "pipe", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPIPE,
172  N_("print dependency set from a command pipe"), NULL },
173 
174  { "perl", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPERL,
175  N_("print perl(...) dependency set"), NULL },
176  { "python", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPYTHON,
177  N_("print python(...) dependency set"), NULL },
178  { "libtool", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSLIBTOOL,
179  N_("print libtool(...) dependency set"), NULL },
180  { "pkgconfig", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPKGCONFIG,
181  N_("print pkgconfig(...) dependency set"), NULL },
182 
183  { "pubkey", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPUBKEY,
184  N_("print pubkey(...) dependency set"), NULL },
185  { "arch", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSARCH,
186  N_("print arch(...) dependency set"), NULL },
187  { "file", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSFILE,
188  N_("print file(...) dependency set"), NULL },
189  { "soname", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSSONAME,
190  N_("print soname(...) dependency set"), NULL },
191  { "package", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPACKAGE,
192  N_("print package(...) dependency set"), NULL },
193 
194  { "java", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSJAVA,
195  N_("print java(...) dependency set"), NULL },
196  { "php", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSPHP,
197  N_("print php(...) dependency set"), NULL },
198  { "ruby", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSRUBY,
199  N_("print ruby(...) dependency set"), NULL },
200  { "dpkgrpm", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSDPKGRPM,
201  N_("print /var/lib/dpkg Provides: dependency set"), NULL },
202  { "rpmdpkg", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &rpmdeps_mode, RPMDEP_RPMDSRPMDPKG,
203  N_("print /var/lib/dpkg Requires: dependency set"), NULL },
204 
205  { "provides", 'P', POPT_ARG_VAL, &print_provides, -1,
206  N_("print Provides: dependency set"), NULL },
207  { "requires", 'R', POPT_ARG_VAL, &print_requires, -1,
208  N_("print Requires: dependency set"), NULL },
209  { "closure", 0, POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &print_closure, -1,
210  N_("check Requires: against Provides: for dependency closure"), NULL },
211 
212  POPT_AUTOALIAS
213  POPT_AUTOHELP
214  POPT_TABLEEND
215 };
216 
217 int
218 main(int argc, char *const argv[])
219 {
220  poptContext optCon;
221  ARGV_t av = NULL;
222  rpmfc fc = NULL;
223  rpmds P = NULL;
224  rpmds R = NULL;
225  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
226 const char * closure_name = "for";
227  FILE * fp = NULL;
228  int flags = 0;
229  int ac = 0;
230  int ec = 1;
231  int xx;
232  int i;
233 char buf[BUFSIZ];
234 
235 /*@-modobserver@*/
236  if ((progname = strrchr(argv[0], '/')) != NULL)
237  progname++;
238  else
239  progname = argv[0];
240 /*@=modobserver@*/
241 
242  optCon = rpmcliInit(argc, argv, optionsTable);
243  if (optCon == NULL)
244  goto exit;
245 
246  av = poptGetArgs(optCon);
247  ac = argvCount(av);
248 
249  if (rpmdeps_mode == RPMDEP_RPMFC && ac == 0) {
250  av = NULL;
251  xx = argvFgets(&av, NULL);
252  ac = argvCount(av);
253  }
254 
255  /* Make sure file names are sorted. */
256  xx = argvSort(av, NULL);
257 
258  switch (rpmdeps_mode) {
259  case RPMDEP_RPMFC:
260  if (ac <= 0) /* XXX avoid rpmfcApply() segfault */
261  break;
262 
263  /* Build file class dictionary. */
264  fc = rpmfcNew();
265  xx = rpmfcClassify(fc, av, NULL);
266 
267  /* Build file/package dependency dictionary. */
268  xx = rpmfcApply(fc);
269 
270 if (_rpmfc_debug) {
271 sprintf(buf, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
272 rpmfcPrint(buf, fc, NULL);
273 }
274  if (print_provides > 0) print_provides = 0;
275  if (print_requires > 0) print_requires = 0;
276  P = fc->provides; fc->provides = NULL;
277  R = fc->requires; fc->requires = NULL;
278  fp = stdout;
279  break;
280  case RPMDEP_RPMDSCPUINFO:
281  closure_name = "cpuinfo(...)";
282  xx = rpmdsCpuinfo(&P, NULL);
283  break;
284  case RPMDEP_RPMDSRPMLIB:
285  closure_name = "rpmlib(...)";
286  xx = rpmdsRpmlib(&P, NULL);
287  break;
288  case RPMDEP_RPMDSSYSINFO:
289  xx = rpmdsSysinfo(PRCO, NULL);
290  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), __FUNCTION__);
291  R = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_REQUIRENAME), __FUNCTION__);
292  break;
293  case RPMDEP_RPMDSGETCONF:
294  closure_name = "getconf(...)";
295  xx = rpmdsGetconf(&P, NULL);
296  break;
297  case RPMDEP_RPMDSELF:
298  closure_name = "soname(...)";
299  for (i = 0; i < ac; i++)
300  xx = rpmdsELF(av[i], flags, rpmdsMergePRCO, PRCO);
301  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), __FUNCTION__);
302  R = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_REQUIRENAME), __FUNCTION__);
303  break;
305  closure_name = "soname(...)";
306  xx = rpmdsLdconfig(PRCO, NULL);
307  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), __FUNCTION__);
308  R = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_REQUIRENAME), __FUNCTION__);
309  break;
310  case RPMDEP_RPMDSUNAME:
311  closure_name = "uname(...)";
312  xx = rpmdsUname(&P, NULL);
313  break;
314 
315  case RPMDEP_RPMDSPIPE:
316  break;
317  case RPMDEP_RPMDSPERL:
318  closure_name = "perl(...)";
319 if (rpmIsVerbose())
320 fprintf(stderr, "\n*** Gathering %s Provides: using\n\t%s\n", closure_name, _perl_provides);
322 if (print_closure || rpmIsVerbose()) {
323 fprintf(stderr, "\n*** Gathering %s Requires: using\n\t%s\n", closure_name, _perl_requires);
325  print_closure = 1;
326 }
327  break;
328  case RPMDEP_RPMDSPYTHON:
329  break;
330  case RPMDEP_RPMDSLIBTOOL:
331  closure_name = "libtool(...)";
332 if (rpmIsVerbose())
333 fprintf(stderr, "\n*** Gathering %s Provides: using\n\t%s\n", closure_name, _libtool_provides);
335 if (print_closure || rpmIsVerbose()) {
336 fprintf(stderr, "\n*** Gathering %s Requires: using\n\t%s\n", closure_name, _libtool_requires);
338  print_closure = 1;
339 }
340  break;
342  closure_name = "pkgconfig(...)";
343 if (rpmIsVerbose())
344 fprintf(stderr, "\n*** Gathering %s Provides: using\n\t%s\n", closure_name, _pkgconfig_provides);
346 if (print_closure || rpmIsVerbose()) {
347 fprintf(stderr, "\n*** Gathering %s Requires: using\n\t%s\n", closure_name, _pkgconfig_requires);
349  print_closure = 1;
350 }
351  break;
352 
353  case RPMDEP_RPMDSPUBKEY:
354  break;
355  case RPMDEP_RPMDSARCH:
356  break;
357  case RPMDEP_RPMDSFILE:
358 if (rpmIsVerbose())
359 fprintf(stderr, "\n*** Gathering rpmdb file Requires: using\n\t%s\n", _rpmdb_file_requires);
361  break;
362  case RPMDEP_RPMDSSONAME:
363  closure_name = "soname(...)";
364  xx = rpmdsLdconfig(PRCO, NULL);
365  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), __FUNCTION__);
366 if (print_closure || rpmIsVerbose()) {
367 fprintf(stderr, "\n*** Gathering rpmdb soname Requires: using\n\t%s\n", _rpmdb_soname_requires);
369  print_closure = 1;
370 }
371  break;
372  case RPMDEP_RPMDSPACKAGE:
373  closure_name = "package(...)";
374 if (rpmIsVerbose())
375 fprintf(stderr, "\n*** Gathering rpmdb package Provides: using\n\t%s\n", _rpmdb_package_provides);
377 if (print_closure || rpmIsVerbose()) {
378 fprintf(stderr, "\n*** Gathering rpmdb package Requires: using\n\t%s\n", _rpmdb_package_requires);
380  print_closure = 1;
381 }
382  break;
383 
384  case RPMDEP_RPMDSJAVA:
385  closure_name = "java(...)";
386 if (rpmIsVerbose())
387 fprintf(stderr, "\n*** Gathering %s Provides: using\n\t%s\n", closure_name, _java_provides);
389 if (print_closure || rpmIsVerbose()) {
390 fprintf(stderr, "\n*** Gathering %s Requires: using\n\t%s\n", closure_name, _java_requires);
392  print_closure = 1;
393 }
394  break;
395  case RPMDEP_RPMDSRUBY:
396  break;
397  case RPMDEP_RPMDSPHP:
398  break;
399  case RPMDEP_RPMDSDPKGRPM:
400  closure_name = "dpkgrpm(...)";
401 if (rpmIsVerbose())
402 fprintf(stderr, "\n*** Gathering dpkg Provides: using\n\t%s\n", _dpkg_provides);
404 if (print_closure || rpmIsVerbose()) {
405 fprintf(stderr, "\n*** Gathering rpmdb package Requires: using\n\t%s\n", _rpmdb_package_requires);
407  print_closure = 1;
408 }
409  break;
410  case RPMDEP_RPMDSRPMDPKG:
411  closure_name = "rpmdpkg(...)";
412 if (print_closure || rpmIsVerbose()) {
413 fprintf(stderr, "\n*** Gathering rpmdb package Provides: using\n\t%s\n", _rpmdb_package_provides);
415  print_closure = 1;
416 }
417 if (rpmIsVerbose())
418 fprintf(stderr, "\n*** Gathering dpkg Requires: using\n\t%s\n", _dpkg_requires);
420  break;
421  }
422 
423  if (print_provides && P != NULL)
424  xx = rpmdepPrint(NULL, P, fp);
425  if (print_requires && R != NULL)
426  xx = rpmdepPrint(NULL, R, fp);
427  if (print_closure) {
428 if (rpmIsVerbose())
429 fprintf(stderr, "\n*** Checking %s Requires(%d): against Provides(%d): closure:\n", closure_name, rpmdsCount(R), rpmdsCount(P));
430  xx = rpmdsPrintClosure(P, R, fp);
431  }
432 
433  fc = rpmfcFree(fc);
434  P = rpmdsFree(P);
435  R = rpmdsFree(R);
436  PRCO = rpmdsFreePRCO(PRCO);
437 
438  ec = 0;
439 
440 exit:
441  optCon = rpmcliFini(optCon);
442  return ec;
443 }