rpmextractor.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libextractor.
00003      (C) 2002, 2003, 2008 Vidyut Samanta and Christian Grothoff
00004 
00005      libextractor is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published
00007      by the Free Software Foundation; either version 2, or (at your
00008      option) any later version.
00009 
00010      libextractor is distributed in the hope that it will be useful, but
00011      WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      General Public License for more details.
00014 
00015      You should have received a copy of the GNU General Public License
00016      along with libextractor; see the file COPYING.  If not, write to the
00017      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018      Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include "platform.h"
00022 #include "extractor.h"
00023 #include <rpm/rpmlib.h>
00024 #include <rpm/rpmts.h>
00025 #include <pthread.h>
00026 #include <sys/types.h>
00027 #include <signal.h>
00028 
00029 /* ******************** pipe feeder ************************ */
00030 
00031 struct PipeArgs {                              
00032   const char * data;
00033   size_t pos;
00034   size_t size;
00035   int pi[2];
00036   int shutdown;
00037 };
00038 
00039 static void *
00040 pipe_feeder(void * args)
00041 {
00042   ssize_t ret;
00043   struct PipeArgs * p = args;
00044 
00045   while ( (p->shutdown == 0) &&
00046           (0 < (ret = WRITE(p->pi[1],
00047                             &p->data[p->pos],
00048                             p->size - p->pos))) )
00049           p->pos += ret;
00050   CLOSE(p->pi[1]);
00051   return NULL;                      
00052 }
00053 
00054 static void
00055 sigalrmHandler (int sig)
00056 {
00057   /* do nothing */
00058 }
00059 
00060 
00061 /* *************** real libextractor stuff ***************** */
00062 
00063 static struct EXTRACTOR_Keywords *
00064 addKeyword (EXTRACTOR_KeywordType type,
00065             const char *keyword, struct EXTRACTOR_Keywords *next)
00066 {
00067   EXTRACTOR_KeywordList *result;
00068 
00069   if (keyword == NULL)
00070     return next;
00071   result = malloc (sizeof (EXTRACTOR_KeywordList));
00072   result->next = next;
00073   result->keyword = strdup (keyword);
00074   result->keywordType = type;
00075   return result;
00076 }
00077 
00078 typedef struct
00079 {
00080   int_32 rtype;
00081   EXTRACTOR_KeywordType type;
00082 } Matches;
00083 
00084 static Matches tests[] = {
00085   {RPMTAG_NAME, EXTRACTOR_TITLE},
00086   {RPMTAG_VERSION, EXTRACTOR_VERSIONNUMBER},
00087   {RPMTAG_RELEASE, EXTRACTOR_RELEASE},
00088   {RPMTAG_GROUP, EXTRACTOR_GROUP},
00089   {RPMTAG_SIZE, EXTRACTOR_SIZE},
00090   {RPMTAG_URL, EXTRACTOR_RESOURCE_IDENTIFIER},
00091   {RPMTAG_SUMMARY, EXTRACTOR_SUMMARY},
00092   {RPMTAG_PACKAGER, EXTRACTOR_PACKAGER},
00093   {RPMTAG_BUILDTIME, EXTRACTOR_CREATION_DATE},
00094   {RPMTAG_COPYRIGHT, EXTRACTOR_COPYRIGHT},
00095   {RPMTAG_LICENSE, EXTRACTOR_LICENSE},
00096   {RPMTAG_DISTRIBUTION, EXTRACTOR_DISTRIBUTION},
00097   {RPMTAG_BUILDHOST, EXTRACTOR_BUILDHOST},
00098   {RPMTAG_VENDOR, EXTRACTOR_VENDOR},
00099   {RPMTAG_OS, EXTRACTOR_OS},
00100   {RPMTAG_DESCRIPTION, EXTRACTOR_DESCRIPTION},
00101   {0, 0},
00102 };
00103 
00104 static void discardCB() {
00105   /* do nothing! */
00106 }
00107 
00108 /* mimetype = application/x-rpm */
00109 struct EXTRACTOR_Keywords *
00110 libextractor_rpm_extract (const char *filename,
00111                           const char *data,
00112                           size_t size, struct EXTRACTOR_Keywords *prev)
00113 {
00114   struct PipeArgs parg;
00115   pthread_t pthr;
00116   void * unused;
00117   Header hdr;
00118   HeaderIterator hi;
00119   int_32 tag;
00120   int_32 type;
00121   int_32 c;
00122   hPTR_t p;
00123   int i;
00124   FD_t fdi;
00125   rpmRC rc;
00126   rpmts ts;
00127   struct sigaction sig;
00128   struct sigaction old;
00129 
00130   if (0 != pipe(parg.pi))
00131     return prev;
00132   fdi = NULL;
00133   parg.data = data;
00134   parg.pos = 0;
00135   parg.size = size;
00136   parg.shutdown = 0;
00137   if (0 != pthread_create(&pthr,
00138                           NULL,
00139                           &pipe_feeder,
00140                           &parg))
00141     {
00142       CLOSE(parg.pi[0]);
00143       CLOSE(parg.pi[1]);
00144       return prev;
00145     }
00146   rpmlogSetCallback(&discardCB);
00147   fdi = fdDup(parg.pi[0]);
00148   ts = rpmtsCreate();
00149   rc = rpmReadPackageFile (ts, fdi, "GNU libextractor", &hdr);
00150   switch (rc)
00151     {
00152     case RPMRC_OK:
00153     case RPMRC_NOKEY:
00154     case RPMRC_NOTTRUSTED:
00155       break;
00156     case RPMRC_NOTFOUND:
00157     case RPMRC_FAIL:
00158     default:
00159       goto END;
00160     }
00161   prev = addKeyword (EXTRACTOR_MIMETYPE,
00162                      "application/x-rpm", prev);
00163   hi = headerInitIterator (hdr);
00164   while (1 == headerNextIterator (hi, &tag, &type, &p, &c))
00165     {
00166       i = 0;
00167       while (tests[i].rtype != 0)
00168         {
00169           if (tests[i].rtype == tag)
00170             {
00171               switch (type)
00172                 {
00173                 case RPM_STRING_ARRAY_TYPE:
00174                   {
00175                     char *tmp;
00176                     const char *p2;
00177                     int c2;
00178                     int size;
00179 
00180                     c2 = c;
00181                     p2 = p;
00182                     size = 0;
00183                     while (c2--)
00184                       {
00185                         size += strlen (p2);
00186                         p2 = strchr (p2, 0);
00187                         p2++;
00188                       }
00189 
00190                     tmp = malloc (size + 1);
00191                     tmp[0] = '\0';
00192                     while (c--)
00193                       {
00194                         strcat (tmp, p);
00195                         p = strchr (p, 0);
00196                         p++;
00197                       }
00198                     prev = addKeyword (tests[i].type, tmp, prev);
00199                     free (tmp);
00200                     break;
00201                   }
00202                 case RPM_I18NSTRING_TYPE:
00203                   {
00204                     char *tmp;
00205                     const char *p2;
00206                     int c2;
00207                     int size;
00208 
00209                     c2 = c;
00210                     p2 = p;
00211                     p2 += sizeof (char *) * c;
00212                     size = 0;
00213                     while (c2--)
00214                       {
00215                         size += strlen (p2);
00216                         p2 = strchr (p2, 0);
00217                         p2++;
00218                       }
00219 
00220                     tmp = malloc (size + 1);
00221                     tmp[0] = '\0';
00222                     p2 = p;
00223                     p2 += sizeof (char *) * c;
00224                     while (c--)
00225                       {
00226                         strcat (tmp, p2);
00227                         p2 = strchr (p2, 0);
00228                         p2++;
00229                       }
00230                     prev = addKeyword (tests[i].type, tmp, prev);
00231                     free (tmp);
00232                     break;
00233                   }
00234                 case RPM_STRING_TYPE:
00235                   prev = addKeyword (tests[i].type, (char *) p, prev);
00236                   break;
00237                 case RPM_INT32_TYPE:
00238                   {
00239                     if (tag == RPMTAG_BUILDTIME)
00240                       {
00241                         char tmp[30];
00242 
00243                         ctime_r ((time_t *) p, tmp);
00244                         tmp[strlen (tmp) - 1] = '\0';   /* eat linefeed */
00245                         prev = addKeyword (tests[i].type, tmp, prev);
00246                       }
00247                     else
00248                       {
00249                         char tmp[14];
00250 
00251                         sprintf (tmp, "%d", *(int *) p);
00252                         prev = addKeyword (tests[i].type, tmp, prev);
00253                       }
00254                     break;
00255                   }
00256                 }
00257             }
00258           i++;
00259         }
00260       if (((type == RPM_BIN_TYPE) ||
00261            (type == RPM_I18NSTRING_TYPE) ||
00262            (type == RPM_STRING_ARRAY_TYPE)) && (p != NULL))
00263         {
00264           free ((void *) p);
00265         }
00266     }
00267   headerFreeIterator (hi);
00268   headerFree (hdr);
00269   rpmtsFree(ts);
00270  END:                                           
00271   /* make sure SIGALRM does not kill us */
00272   memset (&sig, 0, sizeof (struct sigaction));
00273   memset (&old, 0, sizeof (struct sigaction));
00274   sig.sa_flags = SA_NODEFER;
00275   sig.sa_handler = &sigalrmHandler;
00276   sigaction (SIGALRM, &sig, &old);
00277   parg.shutdown = 1;
00278   pthread_kill(pthr, SIGALRM);
00279   pthread_join(pthr, &unused);
00280   sigaction (SIGALRM, &old, &sig);
00281   Fclose(fdi);
00282   CLOSE(parg.pi[0]);
00283   return prev;
00284 }
00285 
00286 /* end of rpmextractor.c */

Generated on Thu Nov 20 06:44:54 2008 for libextractor by  doxygen 1.5.1