"Fossies" - the Fresh Open Source Software Archive 
Member "libextractor-1.11/src/plugins/rpm_extractor.c" (30 Jan 2021, 11638 Bytes) of package /linux/privat/libextractor-1.11.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "rpm_extractor.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.10_vs_1.11.
1 /*
2 This file is part of libextractor.
3 Copyright (C) 2002, 2003, 2008, 2009, 2012 Vidyut Samanta and Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20 /**
21 * @file plugins/rpm_extractor.c
22 * @brief plugin to support RPM files
23 * @author Christian Grothoff
24 */
25 #include "platform.h"
26 #include "extractor.h"
27 #include <stdint.h>
28 #include <rpm/rpmlib.h>
29 #include <rpm/rpmts.h>
30 #include <rpm/rpmlog.h>
31 #if SOMEBSD
32 #include <pthread_np.h>
33 #else
34 #include <pthread.h>
35 #endif
36 #include <sys/types.h>
37 #include <signal.h>
38
39
40 /**
41 * Closure for the 'pipe_feeder'.
42 */
43 struct PipeArgs
44 {
45
46 /**
47 * Context for reading data from.
48 */
49 struct EXTRACTOR_ExtractContext *ec;
50
51 /**
52 * Lock for synchronizing access to 'ec'.
53 */
54 pthread_mutex_t lock;
55
56 /**
57 * Pipe to write to at [1].
58 */
59 int pi[2];
60
61 /**
62 * Set to 1 if we should stop writing to the pipe.
63 */
64 int shutdown;
65 };
66
67
68 /**
69 * Size of the buffer we use for reading.
70 */
71 #define BUF_SIZE (16 * 1024)
72
73
74 /**
75 * Main function of a helper thread that passes the package data
76 * to librpm.
77 *
78 * @param args the 'struct PipeArgs*'
79 * @return NULL
80 */
81 static void *
82 pipe_feeder (void *args)
83 {
84 struct PipeArgs *p = args;
85 ssize_t rret;
86 ssize_t wret;
87 ssize_t done;
88 void *ptr;
89 char *buf;
90
91 /* buffer is heap-allocated as this is a thread and
92 large stack allocations might not be the best idea */
93 while (0 == p->shutdown)
94 {
95 pthread_mutex_lock (&p->lock);
96 if (-1 == (rret = p->ec->read (p->ec->cls, &ptr, BUF_SIZE)))
97 {
98 pthread_mutex_unlock (&p->lock);
99 break;
100 }
101 pthread_mutex_unlock (&p->lock);
102 if (0 == rret)
103 break;
104 buf = ptr;
105 done = 0;
106 while ( (0 == p->shutdown) &&
107 (done < rret) )
108 {
109 if (-1 == (wret = write (p->pi[1],
110 &buf[done],
111 rret - done)))
112 {
113 break;
114 }
115 if (0 == wret)
116 break;
117 done += wret;
118 }
119 if (done != rret)
120 break;
121 }
122 close (p->pi[1]);
123 return NULL;
124 }
125
126
127 /**
128 * LOG callback called by librpm. Does nothing, we
129 * just need this to override the default behavior.
130 */
131 static int
132 discard_log_callback (rpmlogRec rec,
133 void *ctx)
134 {
135 /* do nothing! */
136 return 0;
137 }
138
139
140 /**
141 * Mapping from RPM tags to LE types.
142 */
143 struct Matches
144 {
145 /**
146 * RPM tag.
147 */
148 int32_t rtype;
149
150 /**
151 * Corresponding LE type.
152 */
153 enum EXTRACTOR_MetaType type;
154 };
155
156
157 /**
158 * List of mappings from RPM tags to LE types.
159 */
160 static struct Matches tests[] = {
161 {RPMTAG_NAME, EXTRACTOR_METATYPE_PACKAGE_NAME},
162 {RPMTAG_VERSION, EXTRACTOR_METATYPE_SOFTWARE_VERSION},
163 {RPMTAG_GROUP, EXTRACTOR_METATYPE_SECTION},
164 {RPMTAG_SIZE, EXTRACTOR_METATYPE_PACKAGE_INSTALLED_SIZE},
165 {RPMTAG_SUMMARY, EXTRACTOR_METATYPE_SUMMARY},
166 {RPMTAG_PACKAGER, EXTRACTOR_METATYPE_PACKAGE_MAINTAINER},
167 {RPMTAG_BUILDTIME, EXTRACTOR_METATYPE_CREATION_DATE},
168 #ifdef RPMTAG_COPYRIGHT
169 {RPMTAG_COPYRIGHT, EXTRACTOR_METATYPE_COPYRIGHT},
170 #endif
171 {RPMTAG_LICENSE, EXTRACTOR_METATYPE_LICENSE},
172 {RPMTAG_DISTRIBUTION, EXTRACTOR_METATYPE_PACKAGE_DISTRIBUTION},
173 {RPMTAG_BUILDHOST, EXTRACTOR_METATYPE_BUILDHOST},
174 {RPMTAG_VENDOR, EXTRACTOR_METATYPE_VENDOR},
175 {RPMTAG_OS, EXTRACTOR_METATYPE_TARGET_OS},
176 {RPMTAG_DESCRIPTION, EXTRACTOR_METATYPE_DESCRIPTION},
177 {RPMTAG_URL, EXTRACTOR_METATYPE_URL},
178 {RPMTAG_DISTURL, EXTRACTOR_METATYPE_URL},
179 {RPMTAG_RELEASE, EXTRACTOR_METATYPE_PACKAGE_VERSION},
180 {RPMTAG_PLATFORM, EXTRACTOR_METATYPE_TARGET_PLATFORM},
181 {RPMTAG_ARCH, EXTRACTOR_METATYPE_TARGET_ARCHITECTURE},
182 {RPMTAG_CONFLICTNAME, EXTRACTOR_METATYPE_PACKAGE_CONFLICTS},
183 {RPMTAG_REQUIRENAME, EXTRACTOR_METATYPE_PACKAGE_DEPENDENCY},
184 {RPMTAG_CONFLICTNAME, EXTRACTOR_METATYPE_PACKAGE_CONFLICTS},
185 {RPMTAG_PROVIDENAME, EXTRACTOR_METATYPE_PACKAGE_PROVIDES},
186
187 #if 0
188 {RPMTAG_CHANGELOGTEXT, EXTRACTOR_METATYPE_REVISION_HISTORY},
189 #endif
190
191 #if 0
192 /* FIXME: add support for some of these */
193 RPMTAG_GIF = 1012, /* x */
194 RPMTAG_XPM = 1013, /* x */
195 RPMTAG_SOURCE = 1018, /* s[] */
196 RPMTAG_PATCH = 1019, /* s[] */
197 RPMTAG_PREIN = 1023, /* s */
198 RPMTAG_POSTIN = 1024, /* s */
199 RPMTAG_PREUN = 1025, /* s */
200 RPMTAG_POSTUN = 1026, /* s */
201 RPMTAG_ICON = 1043, /* x */
202 RPMTAG_SOURCERPM = 1044, /* s */
203 RPMTAG_PROVIDENAME = 1047, /* s[] */
204 RPMTAG_EXCLUDEARCH = 1059, /* s[] */
205 RPMTAG_EXCLUDEOS = 1060, /* s[] */
206 RPMTAG_EXCLUSIVEARCH = 1061, /* s[] */
207 RPMTAG_EXCLUSIVEOS = 1062, /* s[] */
208 RPMTAG_TRIGGERSCRIPTS = 1065, /* s[] */
209 RPMTAG_TRIGGERNAME = 1066, /* s[] */
210 RPMTAG_TRIGGERVERSION = 1067, /* s[] */
211 RPMTAG_VERIFYSCRIPT = 1079, /* s */
212 RPMTAG_PREINPROG = 1085, /* s */
213 RPMTAG_POSTINPROG = 1086, /* s */
214 RPMTAG_PREUNPROG = 1087, /* s */
215 RPMTAG_POSTUNPROG = 1088, /* s */
216 RPMTAG_BUILDARCHS = 1089, /* s[] */
217 RPMTAG_OBSOLETENAME = 1090, /* s[] */
218 RPMTAG_VERIFYSCRIPTPROG = 1091, /* s */
219 RPMTAG_TRIGGERSCRIPTPROG = 1092, /* s[] */
220 RPMTAG_COOKIE = 1094, /* s */
221 RPMTAG_FILELANGS = 1097, /* s[] */
222 RPMTAG_PREFIXES = 1098, /* s[] */
223 RPMTAG_INSTPREFIXES = 1099, /* s[] */
224 RPMTAG_PROVIDEVERSION = 1113, /* s[] */
225 RPMTAG_OBSOLETEVERSION = 1115, /* s[] */
226 RPMTAG_BASENAMES = 1117, /* s[] */
227 RPMTAG_DIRNAMES = 1118, /* s[] */
228 RPMTAG_OPTFLAGS = 1122, /* s */
229 RPMTAG_PAYLOADFORMAT = 1124, /* s */
230 RPMTAG_PAYLOADCOMPRESSOR = 1125, /* s */
231 RPMTAG_PAYLOADFLAGS = 1126, /* s */
232 RPMTAG_CLASSDICT = 1142, /* s[] */
233 RPMTAG_SOURCEPKGID = 1146, /* x */
234 RPMTAG_PRETRANS = 1151, /* s */
235 RPMTAG_POSTTRANS = 1152, /* s */
236 RPMTAG_PRETRANSPROG = 1153, /* s */
237 RPMTAG_POSTTRANSPROG = 1154, /* s */
238 RPMTAG_DISTTAG = 1155, /* s */
239 #endif
240 {0, 0}
241 };
242
243
244 /**
245 * Main entry method for the 'application/x-rpm' extraction plugin.
246 *
247 * @param ec extraction context provided to the plugin
248 */
249 void
250 EXTRACTOR_rpm_extract_method (struct EXTRACTOR_ExtractContext *ec)
251 {
252 struct PipeArgs parg;
253 pthread_t pthr;
254 void *unused;
255 const char *str;
256 Header hdr;
257 HeaderIterator hi;
258 rpmtd p;
259 int i;
260 FD_t fdi;
261 rpmRC rc;
262 rpmts ts;
263 struct sigaction sig;
264 struct sigaction old;
265
266 /* FIXME: here it might be worthwhile to do some minimal
267 check to see if this is actually an RPM before we go
268 and create a pipe and a thread for nothing... */
269 parg.ec = ec;
270 parg.shutdown = 0;
271 if (0 != pipe (parg.pi))
272 return;
273 if (0 != pthread_mutex_init (&parg.lock, NULL))
274 {
275 close (parg.pi[0]);
276 close (parg.pi[1]);
277 return;
278 }
279 if (0 != pthread_create (&pthr,
280 NULL,
281 &pipe_feeder,
282 &parg))
283 {
284 pthread_mutex_destroy (&parg.lock);
285 close (parg.pi[0]);
286 close (parg.pi[1]);
287 return;
288 }
289 rpmlogSetCallback (&discard_log_callback, NULL);
290 fdi = fdDup (parg.pi[0]);
291 ts = rpmtsCreate ();
292 rc = rpmReadPackageFile (ts, fdi, "GNU libextractor", &hdr);
293 switch (rc)
294 {
295 case RPMRC_OK:
296 case RPMRC_NOKEY:
297 case RPMRC_NOTTRUSTED:
298 break;
299 case RPMRC_NOTFOUND:
300 case RPMRC_FAIL:
301 default:
302 goto END;
303 }
304 pthread_mutex_lock (&parg.lock);
305 if (0 != ec->proc (ec->cls,
306 "rpm",
307 EXTRACTOR_METATYPE_MIMETYPE,
308 EXTRACTOR_METAFORMAT_UTF8,
309 "text/plain",
310 "application/x-rpm",
311 strlen ("application/x-rpm") + 1))
312 {
313 pthread_mutex_unlock (&parg.lock);
314 goto END;
315 }
316 pthread_mutex_unlock (&parg.lock);
317 hi = headerInitIterator (hdr);
318 p = rpmtdNew ();
319 while (1 == headerNext (hi, p))
320 for (i = 0; 0 != tests[i].rtype; i++)
321 {
322 if (tests[i].rtype != p->tag)
323 continue;
324 switch (p->type)
325 {
326 case RPM_STRING_ARRAY_TYPE:
327 case RPM_I18NSTRING_TYPE:
328 case RPM_STRING_TYPE:
329 while (NULL != (str = rpmtdNextString (p)))
330 {
331 pthread_mutex_lock (&parg.lock);
332 if (0 != ec->proc (ec->cls,
333 "rpm",
334 tests[i].type,
335 EXTRACTOR_METAFORMAT_UTF8,
336 "text/plain",
337 str,
338 strlen (str) + 1))
339
340 {
341 pthread_mutex_unlock (&parg.lock);
342 goto CLEANUP;
343 }
344 pthread_mutex_unlock (&parg.lock);
345 }
346 break;
347 case RPM_INT32_TYPE:
348 {
349 if (p->tag == RPMTAG_BUILDTIME)
350 {
351 char tmp[80];
352 uint32_t *v = rpmtdNextUint32 (p);
353 time_t tp = (time_t) *v;
354
355 if (NULL == ctime_r (&tp, tmp))
356 break;
357 if ( (strlen (tmp) > 0) &&
358 (isspace ((unsigned char) tmp[strlen (tmp) - 1])) )
359 tmp[strlen (tmp) - 1] = '\0'; /* eat linefeed */
360 pthread_mutex_lock (&parg.lock);
361 if (0 != ec->proc (ec->cls,
362 "rpm",
363 tests[i].type,
364 EXTRACTOR_METAFORMAT_UTF8,
365 "text/plain",
366 tmp,
367 strlen (tmp) + 1))
368 {
369 pthread_mutex_unlock (&parg.lock);
370 goto CLEANUP;
371 }
372 pthread_mutex_unlock (&parg.lock);
373 }
374 else
375 {
376 char tmp[14];
377 uint32_t *s = rpmtdNextUint32 (p);
378
379 snprintf (tmp,
380 sizeof (tmp),
381 "%u",
382 (unsigned int) *s);
383 pthread_mutex_lock (&parg.lock);
384 if (0 != ec->proc (ec->cls,
385 "rpm",
386 tests[i].type,
387 EXTRACTOR_METAFORMAT_UTF8,
388 "text/plain",
389 tmp,
390 strlen (tmp) + 1))
391 {
392 pthread_mutex_unlock (&parg.lock);
393 goto CLEANUP;
394 }
395 pthread_mutex_unlock (&parg.lock);
396 }
397 break;
398 }
399 default:
400 break;
401 }
402 }
403 CLEANUP:
404 rpmtdFree (p);
405 headerFreeIterator (hi);
406
407 END:
408 headerFree (hdr);
409 rpmtsFree (ts);
410
411 /* make sure SIGALRM does not kill us, then use it to
412 kill the thread */
413 memset (&sig, 0, sizeof (struct sigaction));
414 memset (&old, 0, sizeof (struct sigaction));
415 sig.sa_flags = SA_NODEFER;
416 sig.sa_handler = SIG_IGN;
417 sigaction (SIGALRM, &sig, &old);
418 parg.shutdown = 1;
419 close (parg.pi[0]);
420 Fclose (fdi);
421 pthread_kill (pthr, SIGALRM);
422 pthread_join (pthr, &unused);
423 pthread_mutex_destroy (&parg.lock);
424 sigaction (SIGALRM, &old, &sig);
425 }
426
427
428 /* end of rpm_extractor.c */