Branch data Line data Source code
1 : : // systemtap debuginfo rpm finder
2 : : // Copyright (C) 2009-2011 Red Hat Inc.
3 : : //
4 : : // This file is part of systemtap, and is free software. You can
5 : : // redistribute it and/or modify it under the terms of the GNU General
6 : : // Public License (GPL); either version 2, or (at your option) any
7 : : // later version.
8 : :
9 : : #include "config.h"
10 : : #include "session.h"
11 : : #include "rpm_finder.h"
12 : :
13 : : #include <iostream>
14 : : #include <fstream>
15 : : #include <sstream>
16 : : #include <cerrno>
17 : : #include <cstdlib>
18 : :
19 : : using namespace std;
20 : :
21 : : #ifdef HAVE_LIBRPM
22 : :
23 : : extern "C" {
24 : :
25 : : #define _RPM_4_4_COMPAT
26 : : #include <string.h>
27 : : #include <rpm/rpmlib.h>
28 : : #include <rpm/rpmts.h>
29 : : #include <rpm/rpmdb.h>
30 : : #include <rpm/header.h>
31 : :
32 : : #ifndef xfree
33 : : #define xfree free
34 : : #endif
35 : :
36 : : }
37 : :
38 : : #if ! HAVE_LIBRPMIO && HAVE_NSS
39 : : extern "C" {
40 : : #include <nss.h>
41 : : }
42 : : #include "nsscommon.h"
43 : : #endif
44 : :
45 : : /* Returns the count of newly added rpms. */
46 : : /* based on the code in F11 gdb-6.8.50.20090302 source rpm */
47 : : /* Added in the rpm_type parameter to specify what rpm to look for */
48 : :
49 : : static int
50 : 10 : missing_rpm_enlist (systemtap_session& sess, const char *filename, const char *rpm_type)
51 : : {
52 : : static int rpm_init_done = 0;
53 : : rpmts ts;
54 : : rpmdbMatchIterator mi;
55 : 10 : int count = 0;
56 : :
57 [ - + ]: 10 : if (filename == NULL)
58 : 0 : return 0;
59 : :
60 [ + + ]: 10 : if (!rpm_init_done)
61 : : {
62 : : static int init_tried;
63 : :
64 : : /* Already failed the initialization before? */
65 [ - + ]: 6 : if (init_tried)
66 : 0 : return 0;
67 : 6 : init_tried = 1;
68 : :
69 [ - + ]: 6 : if (rpmReadConfigFiles(NULL, NULL) != 0)
70 : : {
71 : 0 : cerr << _("Error reading the rpm configuration files") << endl;
72 : 0 : return 0;
73 : : }
74 : :
75 : 6 : rpm_init_done = 1;
76 : : }
77 : :
78 : 10 : ts = rpmtsCreate();
79 : :
80 : 10 : mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, filename, 0);
81 [ + + ]: 10 : if (mi != NULL)
82 : : {
83 : 8 : for (;;)
84 : : {
85 : : Header h;
86 : : char *rpminfo, *s, *s2;
87 : 16 : char header[31] = {};
88 : 16 : const char* arch = ".%{arch}";
89 : 16 : sprintf(header, "%%{sourcerpm}%s%s", rpm_type, arch);
90 : : errmsg_t err;
91 : 16 : size_t rpminfolen = strlen(rpm_type);
92 : 16 : size_t srcrpmlen = sizeof (".src.rpm") - 1;
93 : : rpmdbMatchIterator mi_rpminfo;
94 [ + - ]: 16 : h = rpmdbNextIterator(mi);
95 [ + + ]: 16 : if (h == NULL)
96 : : break;
97 : : /* Verify the kernel file is not already installed. */
98 : :
99 : : rpminfo = headerSprintf(h, header,
100 [ + - ]: 8 : rpmTagTable, rpmHeaderFormats, &err);
101 : :
102 [ - + ]: 8 : if (!rpminfo)
103 : : {
104 [ # # ][ # # ]: 0 : cerr << _("Error querying the rpm file `") << filename << "': "
[ # # ]
105 [ # # ][ # # ]: 0 : << err << endl;
106 : 0 : continue;
107 : : }
108 : : /* s = `.src.rpm-debuginfo.%{arch}' */
109 : 8 : s = strrchr (rpminfo, '-') - srcrpmlen;
110 : 8 : s2 = NULL;
111 [ + - ][ + - ]: 8 : if (s > rpminfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
112 : : {
113 : : /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
114 : 8 : s2 = (char *) memrchr (rpminfo, '-', s - rpminfo);
115 : : }
116 [ + - ]: 8 : if (s2)
117 : : {
118 : : /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
119 : 8 : s2 = (char *) memrchr (rpminfo, '-', s2 - rpminfo);
120 : : }
121 [ - + ]: 8 : if (!s2)
122 : : {
123 [ # # ][ # # ]: 0 : cerr << _("Error querying the rpm file `") << filename
124 [ # # ][ # # ]: 0 : << "': " << rpminfo << endl;
[ # # ]
125 : 0 : xfree (rpminfo);
126 : 0 : continue;
127 : : }
128 : : /* s = `.src.rpm-debuginfo.%{arch}' */
129 : : /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
130 : 8 : memmove (s2 + rpminfolen, s2, s - s2);
131 : 8 : memcpy (s2, rpm_type, rpminfolen);
132 : : /* s = `XXXX.%{arch}' */
133 : : /* strlen ("XXXX") == srcrpmlen + debuginfolen */
134 : : /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
135 : : /* strlen ("XX") == srcrpmlen */
136 : 8 : memmove (s + rpminfolen, s + srcrpmlen + rpminfolen,
137 : 8 : strlen (s + srcrpmlen + rpminfolen) + 1);
138 : : /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
139 : :
140 : : /* RPMDBI_PACKAGES requires keylen == sizeof (int). */
141 : : /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */
142 : : mi_rpminfo = rpmtsInitIterator(ts, (rpmTag) RPMDBI_LABEL,
143 [ + - ]: 8 : rpminfo, 0);
144 [ - + ]: 8 : if (mi_rpminfo)
145 : : {
146 [ # # ]: 0 : rpmdbFreeIterator(mi_rpminfo);
147 : 0 : count = 0;
148 : : break;
149 : : }
150 : : /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
151 [ + - ]: 8 : if(strcmp(rpm_type,"-debuginfo")==0){
152 : 8 : xfree(rpminfo);
153 : : rpminfo = headerSprintf(h,
154 : : "%{name}-%{version}-%{release}.%{arch}",
155 [ + - ]: 8 : rpmTagTable, rpmHeaderFormats, &err);
156 : : }
157 [ - + ]: 8 : if (!rpminfo)
158 : : {
159 [ # # ][ # # ]: 0 : cerr << _("Error querying the rpm file `") << filename
160 [ # # ][ # # ]: 0 : << "': " << err << endl;
[ # # ]
161 : 0 : continue;
162 : : }
163 : :
164 : : /* Base package name for `debuginfo-install'. We do not use the
165 : : `yum' command directly as the line
166 : : yum --enablerepo='*-debuginfo' install NAME-debuginfo.ARCH
167 : : would be more complicated than just:
168 : : debuginfo-install NAME-VERSION-RELEASE.ARCH
169 : : Do not supply the rpm base name (derived from .src.rpm name) as
170 : : debuginfo-install is unable to install the debuginfo package if
171 : : the base name PKG binary rpm is not installed while for example
172 : : PKG-libs would be installed (RH Bug 467901).
173 : : FUTURE: After multiple debuginfo versions simultaneously installed
174 : : get supported the support for the VERSION-RELEASE tags handling
175 : : may need an update. */
176 [ + - ][ + - ]: 8 : sess.rpms_to_install.insert(rpminfo);
[ + - ]
177 : : }
178 : 8 : count++;
179 : 8 : rpmdbFreeIterator(mi);
180 : : }
181 : :
182 : 10 : rpmtsFree(ts);
183 : :
184 : : #if HAVE_NSS
185 : : // librpm uses NSS cryptography but doesn't shut down NSS when it is done.
186 : : // If NSS is available, it will be used by the compile server client on
187 : : // specific certificate databases and thus, it must be shut down first.
188 : : // Get librpm to do it if we can. Otherwise do it ourselves.
189 : : #if HAVE_LIBRPMIO
190 : 10 : rpmFreeCrypto (); // Shuts down NSS within librpm
191 : : #else
192 : : nssCleanup (NULL); // Shut down NSS ourselves
193 : : #endif
194 : : #endif
195 : :
196 : 10 : return count;
197 : : }
198 : : #endif /* HAVE_LIBRPM */
199 : :
200 : : void
201 : 0 : missing_rpm_list_print (systemtap_session &sess, const char* rpm_type)
202 : : {
203 : : #ifdef HAVE_LIBRPM
204 [ # # ][ # # ]: 0 : if (sess.rpms_to_install.size() > 0 && ! sess.suppress_warnings) {
[ # # ]
205 : :
206 [ # # ]: 0 : if(strcmp(rpm_type,"-devel")==0)
207 : 0 : cerr << _("Incorrect version or missing kernel-devel package, use: yum install ");
208 : :
209 [ # # ]: 0 : else if(strcmp(rpm_type,"-debuginfo")==0)
210 : 0 : cerr << _("Missing separate debuginfos, use: debuginfo-install ");
211 : :
212 : : else{
213 : 0 : cerr << _("Incorrect parameter passed, please report this error.") << endl;
214 : 0 : _exit(1);
215 : : }
216 : :
217 [ # # ][ # # ]: 0 : for (set<std::string>::iterator it=sess.rpms_to_install.begin();
218 [ # # ]: 0 : it !=sess.rpms_to_install.end(); it++)
219 : : {
220 [ # # ][ # # ]: 0 : cerr << *it << " ";
221 : : }
222 : 0 : cerr << endl;
223 : : }
224 : : #endif
225 : 0 : }
226 : :
227 : : int
228 : 10 : find_debug_rpms (systemtap_session &sess, const char * filename)
229 : : {
230 : : #ifdef HAVE_LIBRPM
231 : 10 : const char *rpm_type = "-debuginfo";
232 : 10 : return missing_rpm_enlist(sess, filename, rpm_type);
233 : : #else
234 : : return 0;
235 : : #endif
236 : : }
237 : :
238 : 0 : int find_devel_rpms(systemtap_session &sess, const char * filename)
239 : : {
240 : : #ifdef HAVE_LIBRPM
241 : 0 : const char *rpm_type = "-devel";
242 : 0 : return missing_rpm_enlist(sess, filename, rpm_type);
243 : : #else
244 : : return 0;
245 : : #endif
246 [ + - ][ + - ]: 7242 : }
|