libextractor  1.11
About: GNU libextractor is a library used to extract meta-data from files of arbitrary type.
  Fossies Dox: libextractor-1.11.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

rpm_extractor.c
Go to the documentation of this file.
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  */
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  */
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},
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},
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
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",
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,
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,
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,
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 */
@ EXTRACTOR_METAFORMAT_UTF8
Definition: extractor.h:102
#define NULL
Definition: getopt1.c:60
EXTRACTOR_MetaType
Definition: extractor.h:126
@ EXTRACTOR_METATYPE_SECTION
Definition: extractor.h:212
@ EXTRACTOR_METATYPE_SUMMARY
Definition: extractor.h:187
@ EXTRACTOR_METATYPE_PACKAGE_INSTALLED_SIZE
Definition: extractor.h:221
@ EXTRACTOR_METATYPE_TARGET_ARCHITECTURE
Definition: extractor.h:224
@ EXTRACTOR_METATYPE_PACKAGE_PROVIDES
Definition: extractor.h:217
@ EXTRACTOR_METATYPE_PACKAGE_DEPENDENCY
Definition: extractor.h:214
@ EXTRACTOR_METATYPE_TARGET_PLATFORM
Definition: extractor.h:232
@ EXTRACTOR_METATYPE_VENDOR
Definition: extractor.h:229
@ EXTRACTOR_METATYPE_PACKAGE_DISTRIBUTION
Definition: extractor.h:227
@ EXTRACTOR_METATYPE_PACKAGE_VERSION
Definition: extractor.h:211
@ EXTRACTOR_METATYPE_CREATION_DATE
Definition: extractor.h:196
@ EXTRACTOR_METATYPE_PACKAGE_CONFLICTS
Definition: extractor.h:215
@ EXTRACTOR_METATYPE_LICENSE
Definition: extractor.h:226
@ EXTRACTOR_METATYPE_REVISION_HISTORY
Definition: extractor.h:203
@ EXTRACTOR_METATYPE_COPYRIGHT
Definition: extractor.h:183
@ EXTRACTOR_METATYPE_TARGET_OS
Definition: extractor.h:230
@ EXTRACTOR_METATYPE_MIMETYPE
Definition: extractor.h:129
@ EXTRACTOR_METATYPE_PACKAGE_NAME
Definition: extractor.h:210
@ EXTRACTOR_METATYPE_BUILDHOST
Definition: extractor.h:228
@ EXTRACTOR_METATYPE_URL
Definition: extractor.h:159
@ EXTRACTOR_METATYPE_SOFTWARE_VERSION
Definition: extractor.h:231
@ EXTRACTOR_METATYPE_PACKAGE_MAINTAINER
Definition: extractor.h:220
@ EXTRACTOR_METATYPE_DESCRIPTION
Definition: extractor.h:182
plaform specifics
void EXTRACTOR_rpm_extract_method(struct EXTRACTOR_ExtractContext *ec)
static void * pipe_feeder(void *args)
Definition: rpm_extractor.c:82
static struct Matches tests[]
#define BUF_SIZE
Definition: rpm_extractor.c:71
static int discard_log_callback(rpmlogRec rec, void *ctx)
EXTRACTOR_MetaDataProcessor proc
Definition: extractor.h:525
ssize_t(* read)(void *cls, void **data, size_t size)
Definition: extractor.h:494
int32_t rtype
ttag_t tag
enum EXTRACTOR_MetaType type
Definition: deb_extractor.c:82
struct EXTRACTOR_ExtractContext * ec
Definition: rpm_extractor.c:49
int pi[2]
Definition: rpm_extractor.c:59
int shutdown
Definition: rpm_extractor.c:64
pthread_mutex_t lock
Definition: rpm_extractor.c:54