"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 */