00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00058 }
00059
00060
00061
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
00106 }
00107
00108
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';
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
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