aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/extract.c1015
-rw-r--r--src/main/extractor.c532
-rw-r--r--src/main/extractor_common.c49
-rw-r--r--src/main/extractor_common.h10
-rw-r--r--src/main/extractor_datasource.c1083
-rw-r--r--src/main/extractor_datasource.h28
-rw-r--r--src/main/extractor_ipc.c157
-rw-r--r--src/main/extractor_ipc.h57
-rw-r--r--src/main/extractor_ipc_gnu.c389
-rw-r--r--src/main/extractor_ipc_w32.c223
-rw-r--r--src/main/extractor_logging.c11
-rw-r--r--src/main/extractor_logging.h14
-rw-r--r--src/main/extractor_metatypes.c278
-rw-r--r--src/main/extractor_plugin_main.c524
-rw-r--r--src/main/extractor_plugin_main.h4
-rw-r--r--src/main/extractor_plugins.c313
-rw-r--r--src/main/extractor_plugins.h2
-rw-r--r--src/main/extractor_plugpath.c445
-rw-r--r--src/main/extractor_plugpath.h4
-rw-r--r--src/main/extractor_print.c75
-rw-r--r--src/main/getopt.c1139
-rw-r--r--src/main/getopt.h31
-rw-r--r--src/main/getopt1.c175
-rw-r--r--src/main/iconv.c27
-rw-r--r--src/main/test2_extractor.c122
-rw-r--r--src/main/test_bzip2.c120
-rw-r--r--src/main/test_extractor.c146
-rw-r--r--src/main/test_file.c120
-rw-r--r--src/main/test_gzip.c124
-rw-r--r--src/main/test_ipc.c134
-rw-r--r--src/main/test_plugin_load_multi.c27
-rw-r--r--src/main/test_plugin_loading.c33
-rw-r--r--src/main/test_trivial.c22
33 files changed, 3786 insertions, 3647 deletions
diff --git a/src/main/extract.c b/src/main/extract.c
index 2492fa9..144f2c3 100644
--- a/src/main/extract.c
+++ b/src/main/extract.c
@@ -73,6 +73,8 @@ ignore_sigpipe ()
73 FPRINTF (stderr, 73 FPRINTF (stderr,
74 "Failed to install SIGPIPE handler: %s\n", strerror (errno)); 74 "Failed to install SIGPIPE handler: %s\n", strerror (errno));
75} 75}
76
77
76#endif 78#endif
77 79
78 80
@@ -89,17 +91,17 @@ struct Help
89 /** 91 /**
90 * Long name of the option. 92 * Long name of the option.
91 */ 93 */
92 const char * longArg; 94 const char *longArg;
93 95
94 /** 96 /**
95 * Name of the mandatory argument, NULL for no argument. 97 * Name of the mandatory argument, NULL for no argument.
96 */ 98 */
97 const char * mandatoryArg; 99 const char *mandatoryArg;
98 100
99 /** 101 /**
100 * Help text for the option. 102 * Help text for the option.
101 */ 103 */
102 const char * description; 104 const char *description;
103}; 105};
104 106
105 107
@@ -118,8 +120,8 @@ struct Help
118 */ 120 */
119static void 121static void
120format_help (const char *general, 122format_help (const char *general,
121 const char *description, 123 const char *description,
122 const struct Help *opt) 124 const struct Help *opt)
123{ 125{
124 size_t slen; 126 size_t slen;
125 unsigned int i; 127 unsigned int i;
@@ -129,79 +131,80 @@ format_help (const char *general,
129 char scp[80]; 131 char scp[80];
130 const char *trans; 132 const char *trans;
131 133
132 printf (_("Usage: %s\n%s\n\n"), 134 printf (_ ("Usage: %s\n%s\n\n"),
133 gettext(general), 135 gettext (general),
134 gettext(description)); 136 gettext (description));
135 printf (_("Arguments mandatory for long options are also mandatory for short options.\n")); 137 printf (_ (
138 "Arguments mandatory for long options are also mandatory for short options.\n"));
136 slen = 0; 139 slen = 0;
137 i = 0; 140 i = 0;
138 while (NULL != opt[i].description) 141 while (NULL != opt[i].description)
142 {
143 if (0 == opt[i].shortArg)
144 printf (" ");
145 else
146 printf (" -%c, ",
147 opt[i].shortArg);
148 printf ("--%s",
149 opt[i].longArg);
150 slen = 8 + strlen (opt[i].longArg);
151 if (NULL != opt[i].mandatoryArg)
139 { 152 {
140 if (0 == opt[i].shortArg) 153 printf ("=%s",
141 printf (" "); 154 opt[i].mandatoryArg);
142 else 155 slen += 1 + strlen (opt[i].mandatoryArg);
143 printf (" -%c, ", 156 }
144 opt[i].shortArg); 157 if (slen > BORDER)
145 printf ("--%s", 158 {
146 opt[i].longArg); 159 printf ("\n%*s", BORDER, "");
147 slen = 8 + strlen(opt[i].longArg); 160 slen = BORDER;
148 if (NULL != opt[i].mandatoryArg) 161 }
149 { 162 if (slen < BORDER)
150 printf ("=%s", 163 {
151 opt[i].mandatoryArg); 164 printf ("%*s", (int) (BORDER - slen), "");
152 slen += 1+strlen(opt[i].mandatoryArg); 165 slen = BORDER;
153 } 166 }
154 if (slen > BORDER) 167 trans = gettext (opt[i].description);
155 { 168 ml = strlen (trans);
156 printf ("\n%*s", BORDER, ""); 169 p = 0;
157 slen = BORDER; 170OUTER:
158 } 171 while (ml - p > 78 - slen)
159 if (slen < BORDER) 172 {
160 { 173 for (j = p + 78 - slen; j>p; j--)
161 printf ("%*s", (int) (BORDER - slen), ""); 174 {
162 slen = BORDER; 175 if (isspace ( (unsigned char) trans[j]))
163 } 176 {
164 trans = gettext(opt[i].description); 177 memcpy (scp,
165 ml = strlen(trans); 178 &trans[p],
166 p = 0; 179 j - p);
167 OUTER: 180 scp[j - p] = '\0';
168 while (ml - p > 78 - slen) 181 printf ("%s\n%*s",
169 { 182 scp,
170 for (j=p+78-slen;j>p;j--) 183 BORDER + 2,
171 { 184 "");
172 if (isspace( (unsigned char) trans[j])) 185 p = j + 1;
173 { 186 slen = BORDER + 2;
174 memcpy(scp, 187 goto OUTER;
175 &trans[p], 188 }
176 j-p); 189 }
177 scp[j-p] = '\0'; 190 /* could not find space to break line */
178 printf ("%s\n%*s", 191 memcpy (scp,
179 scp, 192 &trans[p],
180 BORDER + 2, 193 78 - slen);
181 ""); 194 scp[78 - slen] = '\0';
182 p = j+1; 195 printf ("%s\n%*s",
183 slen = BORDER + 2; 196 scp,
184 goto OUTER; 197 BORDER + 2,
185 } 198 "");
186 } 199 slen = BORDER + 2;
187 /* could not find space to break line */ 200 p = p + 78 - slen;
188 memcpy (scp,
189 &trans[p],
190 78 - slen);
191 scp[78 - slen] = '\0';
192 printf ("%s\n%*s",
193 scp,
194 BORDER+2,
195 "");
196 slen = BORDER+2;
197 p = p + 78 - slen;
198 }
199 /* print rest */
200 if (p < ml)
201 printf("%s\n",
202 &trans[p]);
203 i++;
204 } 201 }
202 /* print rest */
203 if (p < ml)
204 printf ("%s\n",
205 &trans[p]);
206 i++;
207 }
205} 208}
206 209
207 210
@@ -211,40 +214,43 @@ format_help (const char *general,
211static void 214static void
212print_help () 215print_help ()
213{ 216{
214 static struct Help help[] = 217 static struct Help help[] = {
215 { 218 { 'b', "bibtex", NULL,
216 { 'b', "bibtex", NULL, 219 gettext_noop ("print output in bibtex format") },
217 gettext_noop("print output in bibtex format") }, 220 { 'g', "grep-friendly", NULL,
218 { 'g', "grep-friendly", NULL, 221 gettext_noop (
219 gettext_noop("produce grep-friendly output (all results on one line per file)") }, 222 "produce grep-friendly output (all results on one line per file)") },
220 { 'h', "help", NULL, 223 { 'h', "help", NULL,
221 gettext_noop("print this help") }, 224 gettext_noop ("print this help") },
222 { 'i', "in-process", NULL, 225 { 'i', "in-process", NULL,
223 gettext_noop("run plugins in-process (simplifies debugging)") }, 226 gettext_noop ("run plugins in-process (simplifies debugging)") },
224 { 'm', "from-memory", NULL, 227 { 'm', "from-memory", NULL,
225 gettext_noop("read data from file into memory and extract from memory") }, 228 gettext_noop (
226 { 'l', "library", "LIBRARY", 229 "read data from file into memory and extract from memory") },
227 gettext_noop("load an extractor plugin named LIBRARY") }, 230 { 'l', "library", "LIBRARY",
228 { 'L', "list", NULL, 231 gettext_noop ("load an extractor plugin named LIBRARY") },
229 gettext_noop("list all keyword types") }, 232 { 'L', "list", NULL,
230 { 'n', "nodefault", NULL, 233 gettext_noop ("list all keyword types") },
231 gettext_noop("do not use the default set of extractor plugins") }, 234 { 'n', "nodefault", NULL,
232 { 'p', "print", "TYPE", 235 gettext_noop ("do not use the default set of extractor plugins") },
233 gettext_noop("print only keywords of the given TYPE (use -L to get a list)") }, 236 { 'p', "print", "TYPE",
234 { 'v', "version", NULL, 237 gettext_noop (
235 gettext_noop("print the version number") }, 238 "print only keywords of the given TYPE (use -L to get a list)") },
236 { 'V', "verbose", NULL, 239 { 'v', "version", NULL,
237 gettext_noop("be verbose") }, 240 gettext_noop ("print the version number") },
238 { 'x', "exclude", "TYPE", 241 { 'V', "verbose", NULL,
239 gettext_noop("do not print keywords of the given TYPE") }, 242 gettext_noop ("be verbose") },
240 { 0, NULL, NULL, NULL }, 243 { 'x', "exclude", "TYPE",
241 }; 244 gettext_noop ("do not print keywords of the given TYPE") },
242 format_help (_("extract [OPTIONS] [FILENAME]*"), 245 { 0, NULL, NULL, NULL },
243 _("Extract metadata from files."), 246 };
244 help); 247 format_help (_ ("extract [OPTIONS] [FILENAME]*"),
248 _ ("Extract metadata from files."),
249 help);
245 250
246} 251}
247 252
253
248#if HAVE_ICONV 254#if HAVE_ICONV
249#include "iconv.c" 255#include "iconv.c"
250#endif 256#endif
@@ -267,12 +273,12 @@ print_help ()
267 */ 273 */
268static int 274static int
269print_selected_keywords (void *cls, 275print_selected_keywords (void *cls,
270 const char *plugin_name, 276 const char *plugin_name,
271 enum EXTRACTOR_MetaType type, 277 enum EXTRACTOR_MetaType type,
272 enum EXTRACTOR_MetaFormat format, 278 enum EXTRACTOR_MetaFormat format,
273 const char *data_mime_type, 279 const char *data_mime_type,
274 const char *data, 280 const char *data,
275 size_t data_len) 281 size_t data_len)
276{ 282{
277 char *keyword; 283 char *keyword;
278#if HAVE_ICONV 284#if HAVE_ICONV
@@ -285,59 +291,59 @@ print_selected_keywords (void *cls,
285 return 0; 291 return 0;
286 if (verbose > 3) 292 if (verbose > 3)
287 FPRINTF (stdout, 293 FPRINTF (stdout,
288 _("Found by `%s' plugin:\n"), 294 _ ("Found by `%s' plugin:\n"),
289 plugin_name); 295 plugin_name);
290 mt = EXTRACTOR_metatype_to_string (type); 296 mt = EXTRACTOR_metatype_to_string (type);
291 stype = (NULL == mt) ? _("unknown") : gettext(mt); 297 stype = (NULL == mt) ? _ ("unknown") : gettext (mt);
292 switch (format) 298 switch (format)
293 { 299 {
294 case EXTRACTOR_METAFORMAT_UNKNOWN: 300 case EXTRACTOR_METAFORMAT_UNKNOWN:
295 FPRINTF (stdout, 301 FPRINTF (stdout,
296 _("%s - (unknown, %u bytes)\n"), 302 _ ("%s - (unknown, %u bytes)\n"),
297 stype, 303 stype,
298 (unsigned int) data_len); 304 (unsigned int) data_len);
305 break;
306 case EXTRACTOR_METAFORMAT_UTF8:
307 if (0 == data_len)
299 break; 308 break;
300 case EXTRACTOR_METAFORMAT_UTF8:
301 if (0 == data_len)
302 break;
303#if HAVE_ICONV
304 cd = iconv_open (nl_langinfo(CODESET), "UTF-8");
305 if (((iconv_t) -1) != cd)
306 keyword = iconv_helper (cd,
307 data,
308 data_len);
309 else
310#endif
311 keyword = strdup (data);
312 if (NULL != keyword)
313 {
314 FPRINTF (stdout,
315 "%s - %s\n",
316 stype,
317 keyword);
318 free (keyword);
319 }
320#if HAVE_ICONV 309#if HAVE_ICONV
321 if (((iconv_t) -1) != cd) 310 cd = iconv_open (nl_langinfo (CODESET), "UTF-8");
322 iconv_close (cd); 311 if (((iconv_t) -1) != cd)
312 keyword = iconv_helper (cd,
313 data,
314 data_len);
315 else
323#endif 316#endif
324 break; 317 keyword = strdup (data);
325 case EXTRACTOR_METAFORMAT_BINARY: 318 if (NULL != keyword)
326 FPRINTF (stdout, 319 {
327 _("%s - (binary, %u bytes)\n"),
328 stype,
329 (unsigned int) data_len);
330 break;
331 case EXTRACTOR_METAFORMAT_C_STRING:
332 FPRINTF (stdout, 320 FPRINTF (stdout,
333 "%s - %.*s\n", 321 "%s - %s\n",
334 stype, 322 stype,
335 (int) data_len, 323 keyword);
336 data); 324 free (keyword);
337 break;
338 default:
339 break;
340 } 325 }
326#if HAVE_ICONV
327 if (((iconv_t) -1) != cd)
328 iconv_close (cd);
329#endif
330 break;
331 case EXTRACTOR_METAFORMAT_BINARY:
332 FPRINTF (stdout,
333 _ ("%s - (binary, %u bytes)\n"),
334 stype,
335 (unsigned int) data_len);
336 break;
337 case EXTRACTOR_METAFORMAT_C_STRING:
338 FPRINTF (stdout,
339 "%s - %.*s\n",
340 stype,
341 (int) data_len,
342 data);
343 break;
344 default:
345 break;
346 }
341 return 0; 347 return 0;
342} 348}
343 349
@@ -360,12 +366,12 @@ print_selected_keywords (void *cls,
360 */ 366 */
361static int 367static int
362print_selected_keywords_grep_friendly (void *cls, 368print_selected_keywords_grep_friendly (void *cls,
363 const char *plugin_name, 369 const char *plugin_name,
364 enum EXTRACTOR_MetaType type, 370 enum EXTRACTOR_MetaType type,
365 enum EXTRACTOR_MetaFormat format, 371 enum EXTRACTOR_MetaFormat format,
366 const char *data_mime_type, 372 const char *data_mime_type,
367 const char *data, 373 const char *data,
368 size_t data_len) 374 size_t data_len)
369{ 375{
370 char *keyword; 376 char *keyword;
371#if HAVE_ICONV 377#if HAVE_ICONV
@@ -379,51 +385,51 @@ print_selected_keywords_grep_friendly (void *cls,
379 if (NULL == mt) 385 if (NULL == mt)
380 mt = gettext_noop ("unknown"); 386 mt = gettext_noop ("unknown");
381 switch (format) 387 switch (format)
382 { 388 {
383 case EXTRACTOR_METAFORMAT_UNKNOWN: 389 case EXTRACTOR_METAFORMAT_UNKNOWN:
384 break; 390 break;
385 case EXTRACTOR_METAFORMAT_UTF8: 391 case EXTRACTOR_METAFORMAT_UTF8:
386 if (0 == data_len) 392 if (0 == data_len)
387 return 0; 393 return 0;
388 if (verbose > 1) 394 if (verbose > 1)
389 FPRINTF (stdout, 395 FPRINTF (stdout,
390 "%s: ", 396 "%s: ",
391 gettext(mt)); 397 gettext (mt));
392#if HAVE_ICONV 398#if HAVE_ICONV
393 cd = iconv_open (nl_langinfo (CODESET), "UTF-8"); 399 cd = iconv_open (nl_langinfo (CODESET), "UTF-8");
394 if (((iconv_t) -1) != cd) 400 if (((iconv_t) -1) != cd)
395 keyword = iconv_helper (cd, 401 keyword = iconv_helper (cd,
396 data, 402 data,
397 data_len); 403 data_len);
398 else 404 else
399#endif 405#endif
400 keyword = strdup (data); 406 keyword = strdup (data);
401 if (NULL != keyword) 407 if (NULL != keyword)
402 { 408 {
403 FPRINTF (stdout, 409 FPRINTF (stdout,
404 "`%s' ", 410 "`%s' ",
405 keyword); 411 keyword);
406 free (keyword); 412 free (keyword);
407 } 413 }
408#if HAVE_ICONV 414#if HAVE_ICONV
409 if (((iconv_t) -1) != cd) 415 if (((iconv_t) -1) != cd)
410 iconv_close (cd); 416 iconv_close (cd);
411#endif 417#endif
412 break; 418 break;
413 case EXTRACTOR_METAFORMAT_BINARY: 419 case EXTRACTOR_METAFORMAT_BINARY:
414 break; 420 break;
415 case EXTRACTOR_METAFORMAT_C_STRING: 421 case EXTRACTOR_METAFORMAT_C_STRING:
416 if (verbose > 1) 422 if (verbose > 1)
417 FPRINTF (stdout,
418 "%s ",
419 gettext(mt));
420 FPRINTF (stdout, 423 FPRINTF (stdout,
421 "`%s'", 424 "%s ",
422 data); 425 gettext (mt));
423 break; 426 FPRINTF (stdout,
424 default: 427 "`%s'",
425 break; 428 data);
426 } 429 break;
430 default:
431 break;
432 }
427 return 0; 433 return 0;
428} 434}
429 435
@@ -459,31 +465,30 @@ static char *entry_type;
459 * Mapping between bibTeX strings, libextractor 465 * Mapping between bibTeX strings, libextractor
460 * meta data types and values for the current document. 466 * meta data types and values for the current document.
461 */ 467 */
462static struct BibTexMap btm[] = 468static struct BibTexMap btm[] = {
463 { 469 { "title", EXTRACTOR_METATYPE_TITLE, NULL},
464 { "title", EXTRACTOR_METATYPE_TITLE, NULL}, 470 { "year", EXTRACTOR_METATYPE_PUBLICATION_YEAR, NULL },
465 { "year", EXTRACTOR_METATYPE_PUBLICATION_YEAR, NULL }, 471 { "author", EXTRACTOR_METATYPE_AUTHOR_NAME, NULL },
466 { "author", EXTRACTOR_METATYPE_AUTHOR_NAME, NULL }, 472 { "book", EXTRACTOR_METATYPE_BOOK_TITLE, NULL},
467 { "book", EXTRACTOR_METATYPE_BOOK_TITLE, NULL}, 473 { "edition", EXTRACTOR_METATYPE_BOOK_EDITION, NULL},
468 { "edition", EXTRACTOR_METATYPE_BOOK_EDITION, NULL}, 474 { "chapter", EXTRACTOR_METATYPE_BOOK_CHAPTER_NUMBER, NULL},
469 { "chapter", EXTRACTOR_METATYPE_BOOK_CHAPTER_NUMBER, NULL}, 475 { "journal", EXTRACTOR_METATYPE_JOURNAL_NAME, NULL},
470 { "journal", EXTRACTOR_METATYPE_JOURNAL_NAME, NULL}, 476 { "volume", EXTRACTOR_METATYPE_JOURNAL_VOLUME, NULL},
471 { "volume", EXTRACTOR_METATYPE_JOURNAL_VOLUME, NULL}, 477 { "number", EXTRACTOR_METATYPE_JOURNAL_NUMBER, NULL},
472 { "number", EXTRACTOR_METATYPE_JOURNAL_NUMBER, NULL}, 478 { "pages", EXTRACTOR_METATYPE_PAGE_COUNT, NULL },
473 { "pages", EXTRACTOR_METATYPE_PAGE_COUNT, NULL }, 479 { "pages", EXTRACTOR_METATYPE_PAGE_RANGE, NULL },
474 { "pages", EXTRACTOR_METATYPE_PAGE_RANGE, NULL }, 480 { "school", EXTRACTOR_METATYPE_AUTHOR_INSTITUTION, NULL},
475 { "school", EXTRACTOR_METATYPE_AUTHOR_INSTITUTION, NULL}, 481 { "publisher", EXTRACTOR_METATYPE_PUBLISHER, NULL },
476 { "publisher", EXTRACTOR_METATYPE_PUBLISHER, NULL }, 482 { "address", EXTRACTOR_METATYPE_PUBLISHER_ADDRESS, NULL },
477 { "address", EXTRACTOR_METATYPE_PUBLISHER_ADDRESS, NULL }, 483 { "institution", EXTRACTOR_METATYPE_PUBLISHER_INSTITUTION, NULL },
478 { "institution", EXTRACTOR_METATYPE_PUBLISHER_INSTITUTION, NULL }, 484 { "series", EXTRACTOR_METATYPE_PUBLISHER_SERIES, NULL},
479 { "series", EXTRACTOR_METATYPE_PUBLISHER_SERIES, NULL}, 485 { "month", EXTRACTOR_METATYPE_PUBLICATION_MONTH, NULL },
480 { "month", EXTRACTOR_METATYPE_PUBLICATION_MONTH, NULL }, 486 { "url", EXTRACTOR_METATYPE_URL, NULL},
481 { "url", EXTRACTOR_METATYPE_URL, NULL}, 487 { "note", EXTRACTOR_METATYPE_COMMENT, NULL},
482 { "note", EXTRACTOR_METATYPE_COMMENT, NULL}, 488 { "eprint", EXTRACTOR_METATYPE_BIBTEX_EPRINT, NULL },
483 { "eprint", EXTRACTOR_METATYPE_BIBTEX_EPRINT, NULL }, 489 { "type", EXTRACTOR_METATYPE_PUBLICATION_TYPE, NULL },
484 { "type", EXTRACTOR_METATYPE_PUBLICATION_TYPE, NULL }, 490 { NULL, 0, NULL }
485 { NULL, 0, NULL } 491};
486 };
487 492
488 493
489/** 494/**
@@ -495,10 +500,10 @@ cleanup_bibtex ()
495 unsigned int i; 500 unsigned int i;
496 501
497 for (i = 0; NULL != btm[i].bibTexName; i++) 502 for (i = 0; NULL != btm[i].bibTexName; i++)
498 { 503 {
499 free (btm[i].value); 504 free (btm[i].value);
500 btm[i].value = NULL; 505 btm[i].value = NULL;
501 } 506 }
502 free (entry_type); 507 free (entry_type);
503 entry_type = NULL; 508 entry_type = NULL;
504} 509}
@@ -522,12 +527,12 @@ cleanup_bibtex ()
522 */ 527 */
523static int 528static int
524print_bibtex (void *cls, 529print_bibtex (void *cls,
525 const char *plugin_name, 530 const char *plugin_name,
526 enum EXTRACTOR_MetaType type, 531 enum EXTRACTOR_MetaType type,
527 enum EXTRACTOR_MetaFormat format, 532 enum EXTRACTOR_MetaFormat format,
528 const char *data_mime_type, 533 const char *data_mime_type,
529 const char *data, 534 const char *data,
530 size_t data_len) 535 size_t data_len)
531{ 536{
532 unsigned int i; 537 unsigned int i;
533 538
@@ -538,13 +543,13 @@ print_bibtex (void *cls,
538 if (EXTRACTOR_METAFORMAT_UTF8 != format) 543 if (EXTRACTOR_METAFORMAT_UTF8 != format)
539 return 0; 544 return 0;
540 if (EXTRACTOR_METATYPE_BIBTEX_ENTRY_TYPE == type) 545 if (EXTRACTOR_METATYPE_BIBTEX_ENTRY_TYPE == type)
541 { 546 {
542 entry_type = strdup (data); 547 entry_type = strdup (data);
543 return 0; 548 return 0;
544 } 549 }
545 for (i = 0; NULL != btm[i].bibTexName; i++) 550 for (i = 0; NULL != btm[i].bibTexName; i++)
546 if ( (NULL == btm[i].value) && 551 if ( (NULL == btm[i].value) &&
547 (btm[i].le_type == type) ) 552 (btm[i].le_type == type) )
548 btm[i].value = strdup (data); 553 btm[i].value = strdup (data);
549 return 0; 554 return 0;
550} 555}
@@ -571,33 +576,33 @@ finish_bibtex (const char *fn)
571 (NULL == btm[1].value) || 576 (NULL == btm[1].value) ||
572 (NULL == btm[2].value) ) 577 (NULL == btm[2].value) )
573 FPRINTF (stdout, 578 FPRINTF (stdout,
574 "@%s %s { ", 579 "@%s %s { ",
575 et, 580 et,
576 fn); 581 fn);
577 else 582 else
578 { 583 {
579 snprintf (temp, 584 snprintf (temp,
580 sizeof (temp), 585 sizeof (temp),
581 "%.5s%.5s%.5s", 586 "%.5s%.5s%.5s",
582 btm[2].value, 587 btm[2].value,
583 btm[1].value, 588 btm[1].value,
584 btm[0].value); 589 btm[0].value);
585 for (n=strlen (temp)-1;n>=0;n-- ) 590 for (n = strlen (temp) - 1; n>=0; n--)
586 if (! isalnum ( (unsigned char) temp[n]) ) 591 if (! isalnum ( (unsigned char) temp[n]) )
587 temp[n] = '_'; 592 temp[n] = '_';
588 else 593 else
589 temp[n] = tolower ( (unsigned char) temp[n]); 594 temp[n] = tolower ( (unsigned char) temp[n]);
590 FPRINTF (stdout, 595 FPRINTF (stdout,
591 "@%s %s { ", 596 "@%s %s { ",
592 et, 597 et,
593 temp); 598 temp);
594 } 599 }
595 for (i=0; NULL != btm[i].bibTexName; i++) 600 for (i = 0; NULL != btm[i].bibTexName; i++)
596 if (NULL != btm[i].value) 601 if (NULL != btm[i].value)
597 FPRINTF (stdout, 602 FPRINTF (stdout,
598 "\t%s = {%s},\n", 603 "\t%s = {%s},\n",
599 btm[i].bibTexName, 604 btm[i].bibTexName,
600 btm[i].value); 605 btm[i].value);
601 FPRINTF (stdout, "%s", "}\n\n"); 606 FPRINTF (stdout, "%s", "}\n\n");
602} 607}
603 608
@@ -612,7 +617,9 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp)
612 DWORD error; 617 DWORD error;
613 618
614 SetLastError (0); 619 SetLastError (0);
615 len = WideCharToMultiByte (cp, 0, wstr, -1, NULL, 0, NULL, (cp == CP_UTF8 || cp == CP_UTF7) ? NULL : &lossy); 620 len = WideCharToMultiByte (cp, 0, wstr, -1, NULL, 0, NULL, (cp == CP_UTF8 ||
621 cp == CP_UTF7) ?
622 NULL : &lossy);
616 error = GetLastError (); 623 error = GetLastError ();
617 if (len <= 0) 624 if (len <= 0)
618 return -1; 625 return -1;
@@ -620,7 +627,9 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp)
620 str = malloc (sizeof (char) * len); 627 str = malloc (sizeof (char) * len);
621 628
622 SetLastError (0); 629 SetLastError (0);
623 lenc = WideCharToMultiByte (cp, 0, wstr, -1, str, len, NULL, (cp == CP_UTF8 || cp == CP_UTF7) ? NULL : &lossy); 630 lenc = WideCharToMultiByte (cp, 0, wstr, -1, str, len, NULL, (cp == CP_UTF8 ||
631 cp == CP_UTF7) ?
632 NULL : &lossy);
624 error = GetLastError (); 633 error = GetLastError ();
625 if (lenc != len) 634 if (lenc != len)
626 { 635 {
@@ -632,6 +641,8 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp)
632 return 1; 641 return 1;
633 return 0; 642 return 0;
634} 643}
644
645
635#endif 646#endif
636 647
637 648
@@ -711,10 +722,10 @@ _get_utf8_args (int argc, char *const *argv, int *u8argc, char ***u8argv)
711 722
712 *u8argv = _make_continuous_arg_copy (wargc, split_u8argv); 723 *u8argv = _make_continuous_arg_copy (wargc, split_u8argv);
713 if (NULL == *u8argv) 724 if (NULL == *u8argv)
714 { 725 {
715 free (split_u8argv); 726 free (split_u8argv);
716 return -1; 727 return -1;
717 } 728 }
718 *u8argc = wargc; 729 *u8argc = wargc;
719 730
720 for (i = 0; i < wargc; i++) 731 for (i = 0; i < wargc; i++)
@@ -756,21 +767,21 @@ main (int argc, char *argv[])
756 int utf8_argc; 767 int utf8_argc;
757 768
758#if ENABLE_NLS 769#if ENABLE_NLS
759 setlocale(LC_ALL, ""); 770 setlocale (LC_ALL, "");
760 textdomain(PACKAGE); 771 textdomain (PACKAGE);
761#endif 772#endif
762#ifndef WINDOWS 773#ifndef WINDOWS
763 ignore_sigpipe (); 774 ignore_sigpipe ();
764#endif 775#endif
765 if (NULL == (print = malloc (sizeof (int) * EXTRACTOR_metatype_get_max ()))) 776 if (NULL == (print = malloc (sizeof (int) * EXTRACTOR_metatype_get_max ())))
766 { 777 {
767 FPRINTF (stderr, 778 FPRINTF (stderr,
768 "malloc failed: %s\n", 779 "malloc failed: %s\n",
769 strerror (errno)); 780 strerror (errno));
770 return 1; 781 return 1;
771 } 782 }
772 for (i = 0; i < EXTRACTOR_metatype_get_max (); i++) 783 for (i = 0; i < EXTRACTOR_metatype_get_max (); i++)
773 print[i] = YES; /* default: print everything */ 784 print[i] = YES; /* default: print everything */
774 785
775 if (0 != _get_utf8_args (argc, argv, &utf8_argc, &utf8_argv)) 786 if (0 != _get_utf8_args (argc, argv, &utf8_argc, &utf8_argv))
776 { 787 {
@@ -779,249 +790,252 @@ main (int argc, char *argv[])
779 } 790 }
780 791
781 while (1) 792 while (1)
793 {
794 static struct option long_options[] = {
795 {"bibtex", 0, 0, 'b'},
796 {"grep-friendly", 0, 0, 'g'},
797 {"help", 0, 0, 'h'},
798 {"in-process", 0, 0, 'i'},
799 {"from-memory", 0, 0, 'm'},
800 {"list", 0, 0, 'L'},
801 {"library", 1, 0, 'l'},
802 {"nodefault", 0, 0, 'n'},
803 {"print", 1, 0, 'p'},
804 {"verbose", 0, 0, 'V'},
805 {"version", 0, 0, 'v'},
806 {"exclude", 1, 0, 'x'},
807 {0, 0, 0, 0}
808 };
809 option_index = 0;
810 c = getopt_long (utf8_argc,
811 utf8_argv,
812 "abghiml:Lnp:vVx:",
813 long_options,
814 &option_index);
815
816 if (c == -1)
817 break; /* No more flags to process */
818 switch (c)
782 { 819 {
783 static struct option long_options[] = { 820 case 'b':
784 {"bibtex", 0, 0, 'b'}, 821 bibtex = YES;
785 {"grep-friendly", 0, 0, 'g'}, 822 if (NULL != processor)
786 {"help", 0, 0, 'h'}, 823 {
787 {"in-process", 0, 0, 'i'}, 824 FPRINTF (stderr,
788 {"from-memory", 0, 0, 'm'}, 825 "%s",
789 {"list", 0, 0, 'L'}, 826 _ (
790 {"library", 1, 0, 'l'}, 827 "Illegal combination of options, cannot combine multiple styles of printing.\n"));
791 {"nodefault", 0, 0, 'n'}, 828 free (utf8_argv);
792 {"print", 1, 0, 'p'}, 829 return 0;
793 {"verbose", 0, 0, 'V'}, 830 }
794 {"version", 0, 0, 'v'}, 831 processor = &print_bibtex;
795 {"exclude", 1, 0, 'x'}, 832 break;
796 {0, 0, 0, 0} 833 case 'g':
797 }; 834 grepfriendly = YES;
798 option_index = 0; 835 if (NULL != processor)
799 c = getopt_long (utf8_argc, 836 {
800 utf8_argv, 837 FPRINTF (stderr,
801 "abghiml:Lnp:vVx:", 838 "%s",
802 long_options, 839 _ (
803 &option_index); 840 "Illegal combination of options, cannot combine multiple styles of printing.\n"));
804 841 free (utf8_argv);
805 if (c == -1) 842 return 0;
806 break; /* No more flags to process */ 843 }
807 switch (c) 844 processor = &print_selected_keywords_grep_friendly;
808 { 845 break;
809 case 'b': 846 case 'h':
810 bibtex = YES; 847 print_help ();
811 if (NULL != processor) 848 free (utf8_argv);
812 { 849 return 0;
813 FPRINTF (stderr, 850 case 'i':
814 "%s", 851 in_process = YES;
815 _("Illegal combination of options, cannot combine multiple styles of printing.\n")); 852 break;
816 free (utf8_argv); 853 case 'm':
817 return 0; 854 from_memory = YES;
818 } 855 break;
819 processor = &print_bibtex; 856 case 'l':
820 break; 857 libraries = optarg;
821 case 'g': 858 break;
822 grepfriendly = YES; 859 case 'L':
823 if (NULL != processor) 860 i = 0;
824 { 861 while (NULL != EXTRACTOR_metatype_to_string (i))
825 FPRINTF (stderr, 862 printf ("%s\n",
826 "%s", 863 gettext (EXTRACTOR_metatype_to_string (i++)));
827 _("Illegal combination of options, cannot combine multiple styles of printing.\n")); 864 free (utf8_argv);
828 free (utf8_argv); 865 return 0;
829 return 0; 866 case 'n':
830 } 867 nodefault = YES;
831 processor = &print_selected_keywords_grep_friendly; 868 break;
832 break; 869 case 'p':
833 case 'h': 870 if (NULL == optarg)
834 print_help (); 871 {
835 free (utf8_argv); 872 FPRINTF (stderr,
836 return 0; 873 _ (
837 case 'i': 874 "You must specify an argument for the `%s' option (option ignored).\n"),
838 in_process = YES; 875 "-p");
839 break; 876 break;
840 case 'm': 877 }
841 from_memory = YES; 878 if (YES == defaultAll)
879 {
880 defaultAll = NO;
881 i = 0;
882 while (NULL != EXTRACTOR_metatype_to_string (i))
883 print[i++] = NO;
884 }
885 i = 0;
886 while (NULL != EXTRACTOR_metatype_to_string (i))
887 {
888 if ( (0 == strcmp (optarg,
889 EXTRACTOR_metatype_to_string (i))) ||
890 (0 == strcmp (optarg,
891 gettext (EXTRACTOR_metatype_to_string (i)))) )
892
893 {
894 print[i] = YES;
842 break; 895 break;
843 case 'l': 896 }
844 libraries = optarg; 897 i++;
845 break; 898 }
846 case 'L': 899 if (NULL == EXTRACTOR_metatype_to_string (i))
847 i = 0; 900 {
848 while (NULL != EXTRACTOR_metatype_to_string (i)) 901 FPRINTF (stderr,
849 printf ("%s\n", 902 "Unknown keyword type `%s', use option `%s' to get a list.\n",
850 gettext(EXTRACTOR_metatype_to_string (i++))); 903 optarg,
851 free (utf8_argv); 904 "-L");
852 return 0; 905 free (utf8_argv);
853 case 'n': 906 return -1;
854 nodefault = YES; 907 }
855 break; 908 break;
856 case 'p': 909 case 'v':
857 if (NULL == optarg) 910 printf ("extract v%s\n", PACKAGE_VERSION);
858 {
859 FPRINTF(stderr,
860 _("You must specify an argument for the `%s' option (option ignored).\n"),
861 "-p");
862 break;
863 }
864 if (YES == defaultAll)
865 {
866 defaultAll = NO;
867 i = 0;
868 while (NULL != EXTRACTOR_metatype_to_string (i))
869 print[i++] = NO;
870 }
871 i = 0;
872 while (NULL != EXTRACTOR_metatype_to_string (i))
873 {
874 if ( (0 == strcmp (optarg,
875 EXTRACTOR_metatype_to_string (i))) ||
876 (0 == strcmp (optarg,
877 gettext(EXTRACTOR_metatype_to_string (i)))) )
878
879 {
880 print[i] = YES;
881 break;
882 }
883 i++;
884 }
885 if (NULL == EXTRACTOR_metatype_to_string (i))
886 {
887 FPRINTF(stderr,
888 "Unknown keyword type `%s', use option `%s' to get a list.\n",
889 optarg,
890 "-L");
891 free (utf8_argv);
892 return -1;
893 }
894 break;
895 case 'v':
896 printf ("extract v%s\n", PACKAGE_VERSION);
897 free (utf8_argv);
898 return 0;
899 case 'V':
900 verbose++;
901 break;
902 case 'x':
903 i = 0;
904 while (NULL != EXTRACTOR_metatype_to_string (i))
905 {
906 if ( (0 == strcmp (optarg,
907 EXTRACTOR_metatype_to_string (i))) ||
908 (0 == strcmp (optarg,
909 gettext(EXTRACTOR_metatype_to_string (i)))) )
910 {
911 print[i] = NO;
912 break;
913 }
914 i++;
915 }
916 if (NULL == EXTRACTOR_metatype_to_string (i))
917 {
918 FPRINTF (stderr,
919 "Unknown keyword type `%s', use option `%s' to get a list.\n",
920 optarg,
921 "-L");
922 free (utf8_argv);
923 return -1;
924 }
925 break;
926 default:
927 FPRINTF (stderr,
928 "%s",
929 _("Use --help to get a list of options.\n"));
930 free (utf8_argv);
931 return -1;
932 } /* end of parsing commandline */
933 } /* while (1) */
934 if (optind < 0)
935 {
936 FPRINTF (stderr,
937 "%s", "Unknown error parsing options\n");
938 free (print);
939 free (utf8_argv); 911 free (utf8_argv);
940 return -1; 912 return 0;
941 } 913 case 'V':
942 if (utf8_argc - optind < 1) 914 verbose++;
943 { 915 break;
916 case 'x':
917 i = 0;
918 while (NULL != EXTRACTOR_metatype_to_string (i))
919 {
920 if ( (0 == strcmp (optarg,
921 EXTRACTOR_metatype_to_string (i))) ||
922 (0 == strcmp (optarg,
923 gettext (EXTRACTOR_metatype_to_string (i)))) )
924 {
925 print[i] = NO;
926 break;
927 }
928 i++;
929 }
930 if (NULL == EXTRACTOR_metatype_to_string (i))
931 {
932 FPRINTF (stderr,
933 "Unknown keyword type `%s', use option `%s' to get a list.\n",
934 optarg,
935 "-L");
936 free (utf8_argv);
937 return -1;
938 }
939 break;
940 default:
944 FPRINTF (stderr, 941 FPRINTF (stderr,
945 "%s", "Invoke with list of filenames to extract keywords form!\n"); 942 "%s",
946 free (print); 943 _ ("Use --help to get a list of options.\n"));
947 free (utf8_argv); 944 free (utf8_argv);
948 return -1; 945 return -1;
949 } 946 } /* end of parsing commandline */
947 } /* while (1) */
948 if (optind < 0)
949 {
950 FPRINTF (stderr,
951 "%s", "Unknown error parsing options\n");
952 free (print);
953 free (utf8_argv);
954 return -1;
955 }
956 if (utf8_argc - optind < 1)
957 {
958 FPRINTF (stderr,
959 "%s", "Invoke with list of filenames to extract keywords form!\n");
960 free (print);
961 free (utf8_argv);
962 return -1;
963 }
950 964
951 /* build list of libraries */ 965 /* build list of libraries */
952 if (NO == nodefault) 966 if (NO == nodefault)
953 plugins = EXTRACTOR_plugin_add_defaults (in_process 967 plugins = EXTRACTOR_plugin_add_defaults (in_process
954 ? EXTRACTOR_OPTION_IN_PROCESS 968 ? EXTRACTOR_OPTION_IN_PROCESS
955 : EXTRACTOR_OPTION_DEFAULT_POLICY); 969 : EXTRACTOR_OPTION_DEFAULT_POLICY);
956 else 970 else
957 plugins = NULL; 971 plugins = NULL;
958 if (NULL != libraries) 972 if (NULL != libraries)
959 plugins = EXTRACTOR_plugin_add_config (plugins, 973 plugins = EXTRACTOR_plugin_add_config (plugins,
960 libraries, 974 libraries,
961 in_process 975 in_process
962 ? EXTRACTOR_OPTION_IN_PROCESS 976 ? EXTRACTOR_OPTION_IN_PROCESS
963 : EXTRACTOR_OPTION_DEFAULT_POLICY); 977 : EXTRACTOR_OPTION_DEFAULT_POLICY);
964 if (NULL == processor) 978 if (NULL == processor)
965 processor = &print_selected_keywords; 979 processor = &print_selected_keywords;
966 980
967 /* extract keywords */ 981 /* extract keywords */
968 if (YES == bibtex) 982 if (YES == bibtex)
969 FPRINTF(stdout, 983 FPRINTF (stdout,
970 "%s", _("% BiBTeX file\n")); 984 "%s", _ ("% BiBTeX file\n"));
971 for (i = optind; i < utf8_argc; i++) 985 for (i = optind; i < utf8_argc; i++)
986 {
987 errno = 0;
988 if (YES == grepfriendly)
989 FPRINTF (stdout, "%s ", utf8_argv[i]);
990 else if (NO == bibtex)
991 FPRINTF (stdout,
992 _ ("Keywords for file %s:\n"),
993 utf8_argv[i]);
994 else
995 cleanup_bibtex ();
996 if (NO == from_memory)
997 EXTRACTOR_extract (plugins,
998 utf8_argv[i],
999 NULL, 0,
1000 processor,
1001 NULL);
1002 else
972 { 1003 {
973 errno = 0; 1004 struct stat sb;
974 if (YES == grepfriendly) 1005 unsigned char *data = NULL;
975 FPRINTF (stdout, "%s ", utf8_argv[i]); 1006 int f = OPEN (utf8_argv[i], O_RDONLY
976 else if (NO == bibtex)
977 FPRINTF (stdout,
978 _("Keywords for file %s:\n"),
979 utf8_argv[i]);
980 else
981 cleanup_bibtex ();
982 if (NO == from_memory)
983 EXTRACTOR_extract (plugins,
984 utf8_argv[i],
985 NULL, 0,
986 processor,
987 NULL);
988 else
989 {
990 struct stat sb;
991 unsigned char *data = NULL;
992 int f = OPEN (utf8_argv[i], O_RDONLY
993#if WINDOWS 1007#if WINDOWS
994 | O_BINARY 1008 | O_BINARY
995#endif 1009#endif
996 ); 1010 );
997 if ( (-1 != f) && 1011 if ( (-1 != f) &&
998 (0 == FSTAT (f, &sb)) && 1012 (0 == FSTAT (f, &sb)) &&
999 (NULL != (data = malloc ((size_t) sb.st_size))) && 1013 (NULL != (data = malloc ((size_t) sb.st_size))) &&
1000 (sb.st_size == READ (f, data, (size_t) sb.st_size) ) ) 1014 (sb.st_size == READ (f, data, (size_t) sb.st_size) ) )
1001 { 1015 {
1002 EXTRACTOR_extract (plugins, 1016 EXTRACTOR_extract (plugins,
1003 NULL, 1017 NULL,
1004 data, sb.st_size, 1018 data, sb.st_size,
1005 processor, 1019 processor,
1006 NULL); 1020 NULL);
1007 } 1021 }
1008 else 1022 else
1009 { 1023 {
1010 if (verbose > 0) 1024 if (verbose > 0)
1011 FPRINTF(stderr, 1025 FPRINTF (stderr,
1012 "%s: %s: %s\n", 1026 "%s: %s: %s\n",
1013 utf8_argv[0], utf8_argv[i], strerror(errno)); 1027 utf8_argv[0], utf8_argv[i], strerror (errno));
1014 ret = 1; 1028 ret = 1;
1015 } 1029 }
1016 if (NULL != data) 1030 if (NULL != data)
1017 free (data); 1031 free (data);
1018 if (-1 != f) 1032 if (-1 != f)
1019 (void) CLOSE (f); 1033 (void) CLOSE (f);
1020 }
1021 if (YES == grepfriendly)
1022 FPRINTF (stdout, "%s", "\n");
1023 continue;
1024 } 1034 }
1035 if (YES == grepfriendly)
1036 FPRINTF (stdout, "%s", "\n");
1037 continue;
1038 }
1025 if (YES == grepfriendly) 1039 if (YES == grepfriendly)
1026 FPRINTF (stdout, "%s", "\n"); 1040 FPRINTF (stdout, "%s", "\n");
1027 if (bibtex) 1041 if (bibtex)
@@ -1036,4 +1050,5 @@ main (int argc, char *argv[])
1036 return ret; 1050 return ret;
1037} 1051}
1038 1052
1053
1039/* end of extract.c */ 1054/* end of extract.c */
diff --git a/src/main/extractor.c b/src/main/extractor.c
index 3755da9..cb64b95 100644
--- a/src/main/extractor.c
+++ b/src/main/extractor.c
@@ -71,9 +71,9 @@ struct PluginReplyProcessor
71 */ 71 */
72static void 72static void
73send_update_message (struct EXTRACTOR_PluginList *plugin, 73send_update_message (struct EXTRACTOR_PluginList *plugin,
74 int64_t shm_off, 74 int64_t shm_off,
75 size_t data_available, 75 size_t data_available,
76 struct EXTRACTOR_Datasource *ds) 76 struct EXTRACTOR_Datasource *ds)
77{ 77{
78 struct UpdateMessage um; 78 struct UpdateMessage um;
79 79
@@ -85,14 +85,14 @@ send_update_message (struct EXTRACTOR_PluginList *plugin,
85 um.file_size = EXTRACTOR_datasource_get_size_ (ds, 0); 85 um.file_size = EXTRACTOR_datasource_get_size_ (ds, 0);
86 if (sizeof (um) != 86 if (sizeof (um) !=
87 EXTRACTOR_IPC_channel_send_ (plugin->channel, 87 EXTRACTOR_IPC_channel_send_ (plugin->channel,
88 &um, 88 &um,
89 sizeof (um)) ) 89 sizeof (um)) )
90 { 90 {
91 LOG ("Failed to send UPDATED_SHM message to plugin\n"); 91 LOG ("Failed to send UPDATED_SHM message to plugin\n");
92 EXTRACTOR_IPC_channel_destroy_ (plugin->channel); 92 EXTRACTOR_IPC_channel_destroy_ (plugin->channel);
93 plugin->channel = NULL; 93 plugin->channel = NULL;
94 plugin->round_finished = 1; 94 plugin->round_finished = 1;
95 } 95 }
96} 96}
97 97
98 98
@@ -109,14 +109,14 @@ send_discard_message (struct EXTRACTOR_PluginList *plugin)
109 109
110 if (sizeof (disc_msg) != 110 if (sizeof (disc_msg) !=
111 EXTRACTOR_IPC_channel_send_ (plugin->channel, 111 EXTRACTOR_IPC_channel_send_ (plugin->channel,
112 &disc_msg, 112 &disc_msg,
113 sizeof (disc_msg)) ) 113 sizeof (disc_msg)) )
114 { 114 {
115 LOG ("Failed to send DISCARD_STATE message to plugin\n"); 115 LOG ("Failed to send DISCARD_STATE message to plugin\n");
116 EXTRACTOR_IPC_channel_destroy_ (plugin->channel); 116 EXTRACTOR_IPC_channel_destroy_ (plugin->channel);
117 plugin->channel = NULL; 117 plugin->channel = NULL;
118 plugin->round_finished = 1; 118 plugin->round_finished = 1;
119 } 119 }
120} 120}
121 121
122 122
@@ -131,12 +131,12 @@ abort_all_channels (struct EXTRACTOR_PluginList *plugins)
131 struct EXTRACTOR_PluginList *pos; 131 struct EXTRACTOR_PluginList *pos;
132 132
133 for (pos = plugins; NULL != pos; pos = pos->next) 133 for (pos = plugins; NULL != pos; pos = pos->next)
134 { 134 {
135 if (NULL == pos->channel) 135 if (NULL == pos->channel)
136 continue; 136 continue;
137 EXTRACTOR_IPC_channel_destroy_ (pos->channel); 137 EXTRACTOR_IPC_channel_destroy_ (pos->channel);
138 pos->channel = NULL; 138 pos->channel = NULL;
139 } 139 }
140} 140}
141 141
142 142
@@ -153,46 +153,46 @@ abort_all_channels (struct EXTRACTOR_PluginList *plugins)
153 */ 153 */
154static void 154static void
155process_plugin_reply (void *cls, 155process_plugin_reply (void *cls,
156 struct EXTRACTOR_PluginList *plugin, 156 struct EXTRACTOR_PluginList *plugin,
157 enum EXTRACTOR_MetaType meta_type, 157 enum EXTRACTOR_MetaType meta_type,
158 enum EXTRACTOR_MetaFormat meta_format, 158 enum EXTRACTOR_MetaFormat meta_format,
159 const char *mime, 159 const char *mime,
160 const void *value, 160 const void *value,
161 size_t value_len) 161 size_t value_len)
162{ 162{
163 static unsigned char cont_msg = MESSAGE_CONTINUE_EXTRACTING; 163 static unsigned char cont_msg = MESSAGE_CONTINUE_EXTRACTING;
164 struct PluginReplyProcessor *prp = cls; 164 struct PluginReplyProcessor *prp = cls;
165 165
166 if (0 != prp->file_finished) 166 if (0 != prp->file_finished)
167 { 167 {
168 /* client already aborted, ignore message, tell plugin about abort */ 168 /* client already aborted, ignore message, tell plugin about abort */
169 return; 169 return;
170 } 170 }
171 if (0 != prp->proc (prp->proc_cls, 171 if (0 != prp->proc (prp->proc_cls,
172 plugin->short_libname, 172 plugin->short_libname,
173 meta_type, 173 meta_type,
174 meta_format, 174 meta_format,
175 mime, 175 mime,
176 value, 176 value,
177 value_len)) 177 value_len))
178 { 178 {
179 prp->file_finished = 1; 179 prp->file_finished = 1;
180#if DEBUG 180#if DEBUG
181 fprintf (stderr, "Sending ABRT\n"); 181 fprintf (stderr, "Sending ABRT\n");
182#endif 182#endif
183 send_discard_message (plugin); 183 send_discard_message (plugin);
184 return; 184 return;
185 } 185 }
186 if (sizeof (cont_msg) != 186 if (sizeof (cont_msg) !=
187 EXTRACTOR_IPC_channel_send_ (plugin->channel, 187 EXTRACTOR_IPC_channel_send_ (plugin->channel,
188 &cont_msg, 188 &cont_msg,
189 sizeof (cont_msg)) ) 189 sizeof (cont_msg)) )
190 { 190 {
191 LOG ("Failed to send CONTINUE_EXTRACTING message to plugin\n"); 191 LOG ("Failed to send CONTINUE_EXTRACTING message to plugin\n");
192 EXTRACTOR_IPC_channel_destroy_ (plugin->channel); 192 EXTRACTOR_IPC_channel_destroy_ (plugin->channel);
193 plugin->channel = NULL; 193 plugin->channel = NULL;
194 plugin->round_finished = 1; 194 plugin->round_finished = 1;
195 } 195 }
196} 196}
197 197
198 198
@@ -245,8 +245,8 @@ struct InProcessContext
245 */ 245 */
246static ssize_t 246static ssize_t
247in_process_read (void *cls, 247in_process_read (void *cls,
248 void **data, 248 void **data,
249 size_t size) 249 size_t size)
250{ 250{
251 struct InProcessContext *ctx = cls; 251 struct InProcessContext *ctx = cls;
252 ssize_t ret; 252 ssize_t ret;
@@ -256,8 +256,8 @@ in_process_read (void *cls,
256 if (size < bsize) 256 if (size < bsize)
257 bsize = size; 257 bsize = size;
258 ret = EXTRACTOR_datasource_read_ (ctx->ds, 258 ret = EXTRACTOR_datasource_read_ (ctx->ds,
259 ctx->buf, 259 ctx->buf,
260 bsize); 260 bsize);
261 if (-1 == ret) 261 if (-1 == ret)
262 *data = NULL; 262 *data = NULL;
263 else 263 else
@@ -279,14 +279,14 @@ in_process_read (void *cls,
279 */ 279 */
280static int64_t 280static int64_t
281in_process_seek (void *cls, 281in_process_seek (void *cls,
282 int64_t pos, 282 int64_t pos,
283 int whence) 283 int whence)
284{ 284{
285 struct InProcessContext *ctx = cls; 285 struct InProcessContext *ctx = cls;
286 286
287 return EXTRACTOR_datasource_seek_ (ctx->ds, 287 return EXTRACTOR_datasource_seek_ (ctx->ds,
288 pos, 288 pos,
289 whence); 289 whence);
290} 290}
291 291
292 292
@@ -326,12 +326,12 @@ in_process_get_size (void *cls)
326 */ 326 */
327static int 327static int
328in_process_proc (void *cls, 328in_process_proc (void *cls,
329 const char *plugin_name, 329 const char *plugin_name,
330 enum EXTRACTOR_MetaType type, 330 enum EXTRACTOR_MetaType type,
331 enum EXTRACTOR_MetaFormat format, 331 enum EXTRACTOR_MetaFormat format,
332 const char *data_mime_type, 332 const char *data_mime_type,
333 const char *data, 333 const char *data,
334 size_t data_len) 334 size_t data_len)
335{ 335{
336 struct InProcessContext *ctx = cls; 336 struct InProcessContext *ctx = cls;
337 int ret; 337 int ret;
@@ -339,12 +339,12 @@ in_process_proc (void *cls,
339 if (0 != ctx->finished) 339 if (0 != ctx->finished)
340 return 1; 340 return 1;
341 ret = ctx->proc (ctx->proc_cls, 341 ret = ctx->proc (ctx->proc_cls,
342 plugin_name, 342 plugin_name,
343 type, 343 type,
344 format, 344 format,
345 data_mime_type, 345 data_mime_type,
346 data, 346 data,
347 data_len); 347 data_len);
348 if (0 != ret) 348 if (0 != ret)
349 ctx->finished = 1; 349 ctx->finished = 1;
350 return ret; 350 return ret;
@@ -363,9 +363,9 @@ in_process_proc (void *cls,
363 */ 363 */
364static void 364static void
365do_extract (struct EXTRACTOR_PluginList *plugins, 365do_extract (struct EXTRACTOR_PluginList *plugins,
366 struct EXTRACTOR_SharedMemory *shm, 366 struct EXTRACTOR_SharedMemory *shm,
367 struct EXTRACTOR_Datasource *ds, 367 struct EXTRACTOR_Datasource *ds,
368 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 368 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
369{ 369{
370 unsigned int plugin_count; 370 unsigned int plugin_count;
371 unsigned int plugin_off; 371 unsigned int plugin_off;
@@ -406,153 +406,153 @@ do_extract (struct EXTRACTOR_PluginList *plugins,
406 start.shm_ready_bytes = (uint32_t) ready; 406 start.shm_ready_bytes = (uint32_t) ready;
407 start.file_size = EXTRACTOR_datasource_get_size_ (ds, 0); 407 start.file_size = EXTRACTOR_datasource_get_size_ (ds, 0);
408 for (pos = plugins; NULL != pos; pos = pos->next) 408 for (pos = plugins; NULL != pos; pos = pos->next)
409 {
410 if (EXTRACTOR_OPTION_IN_PROCESS == pos->flags)
411 have_in_memory = 1;
412 if ( (NULL != pos->channel) &&
413 (-1 == EXTRACTOR_IPC_channel_send_ (pos->channel,
414 &start,
415 sizeof (start)) ) )
409 { 416 {
410 if (EXTRACTOR_OPTION_IN_PROCESS == pos->flags) 417 LOG ("Failed to send EXTRACT_START message to plugin\n");
411 have_in_memory = 1; 418 EXTRACTOR_IPC_channel_destroy_ (pos->channel);
412 if ( (NULL != pos->channel) && 419 pos->channel = NULL;
413 (-1 == EXTRACTOR_IPC_channel_send_ (pos->channel,
414 &start,
415 sizeof (start)) ) )
416 {
417 LOG ("Failed to send EXTRACT_START message to plugin\n");
418 EXTRACTOR_IPC_channel_destroy_ (pos->channel);
419 pos->channel = NULL;
420 }
421 } 420 }
421 }
422 if (-1 == ready) 422 if (-1 == ready)
423 { 423 {
424 LOG ("Failed to initialize IPC shared memory, cannot extract\n"); 424 LOG ("Failed to initialize IPC shared memory, cannot extract\n");
425 done = 1; 425 done = 1;
426 } 426 }
427 else 427 else
428 done = 0; 428 done = 0;
429 while (! done) 429 while (! done)
430 {
431 struct EXTRACTOR_Channel *channels[plugin_count];
432
433 /* calculate current 'channels' array */
434 plugin_off = 0;
435 for (pos = plugins; NULL != pos; pos = pos->next)
430 { 436 {
431 struct EXTRACTOR_Channel *channels[plugin_count]; 437 if (-1 == pos->seek_request)
432 438 {
433 /* calculate current 'channels' array */ 439 /* channel is not seeking, must be running or done */
434 plugin_off = 0; 440 channels[plugin_off] = pos->channel;
435 for (pos = plugins; NULL != pos; pos = pos->next) 441 }
436 { 442 else
437 if (-1 == pos->seek_request) 443 {
438 { 444 /* not running this round, seeking! */
439 /* channel is not seeking, must be running or done */ 445 channels[plugin_off] = NULL;
440 channels[plugin_off] = pos->channel; 446 }
441 } 447 plugin_off++;
442 else 448 }
443 { 449 /* give plugins chance to send us meta data, seek or finished messages */
444 /* not running this round, seeking! */ 450 if (-1 ==
445 channels[plugin_off] = NULL; 451 EXTRACTOR_IPC_channel_recv_ (channels,
446 } 452 plugin_count,
447 plugin_off++; 453 &process_plugin_reply,
448 } 454 &prp))
449 /* give plugins chance to send us meta data, seek or finished messages */ 455 {
450 if (-1 == 456 /* serious problem in IPC; reset *all* channels */
451 EXTRACTOR_IPC_channel_recv_ (channels, 457 LOG ("Failed to receive message from channels; full reset\n");
452 plugin_count, 458 abort_all_channels (plugins);
453 &process_plugin_reply, 459 break;
454 &prp)) 460 }
455 { 461
456 /* serious problem in IPC; reset *all* channels */ 462 /* calculate minimum seek request (or set done=0 to continue here) */
457 LOG ("Failed to receive message from channels; full reset\n"); 463 done = 1;
458 abort_all_channels (plugins); 464 min_seek = -1;
459 break; 465 plugin_off = 0;
460 } 466 for (pos = plugins; NULL != pos; pos = pos->next)
461 467 {
462 /* calculate minimum seek request (or set done=0 to continue here) */ 468 plugin_off++;
463 done = 1; 469 if ( (1 == pos->round_finished) ||
464 min_seek = -1; 470 (NULL == pos->channel) )
465 plugin_off = 0; 471 {
466 for (pos = plugins; NULL != pos; pos = pos->next) 472 continue; /* inactive plugin */
467 { 473 }
468 plugin_off++; 474 if (-1 == pos->seek_request)
469 if ( (1 == pos->round_finished) || 475 {
470 (NULL == pos->channel) ) 476 /* possibly more meta data at current position, at least
477 this plugin is still working on it... */
478 done = 0;
479 break;
480 }
481 if (-1 != pos->seek_request)
482 {
483 if (SEEK_END == pos->seek_whence)
484 {
485 /* convert distance from end to absolute position */
486 pos->seek_whence = 0;
487 end = EXTRACTOR_datasource_get_size_ (ds, 1);
488 if (pos->seek_request > end)
471 { 489 {
472 continue; /* inactive plugin */ 490 LOG ("Cannot seek to before the beginning of the file!\n");
491 pos->seek_request = 0;
473 } 492 }
474 if (-1 == pos->seek_request) 493 else
475 { 494 {
476 /* possibly more meta data at current position, at least 495 pos->seek_request = end - pos->seek_request;
477 this plugin is still working on it... */ 496 }
478 done = 0; 497 }
479 break; 498 if ( (-1 == min_seek) ||
480 } 499 (min_seek > pos->seek_request) )
481 if (-1 != pos->seek_request) 500 {
482 { 501 min_seek = pos->seek_request;
483 if (SEEK_END == pos->seek_whence) 502 }
484 { 503 }
485 /* convert distance from end to absolute position */ 504 }
486 pos->seek_whence = 0; 505 data_available = -1;
487 end = EXTRACTOR_datasource_get_size_ (ds, 1); 506 if ( (1 == done) &&
488 if (pos->seek_request > end) 507 (-1 != min_seek) &&
489 { 508 (NULL != shm) )
490 LOG ("Cannot seek to before the beginning of the file!\n"); 509 {
491 pos->seek_request = 0; 510 /* current position done, but seek requested */
492 } 511 done = 0;
493 else 512 if (-1 ==
494 { 513 (data_available = EXTRACTOR_IPC_shared_memory_set_ (shm,
495 pos->seek_request = end - pos->seek_request; 514 ds,
496 } 515 min_seek,
497 } 516 DEFAULT_SHM_SIZE)))
498 if ( (-1 == min_seek) || 517 {
499 (min_seek > pos->seek_request) ) 518 LOG ("Failed to seek; full reset\n");
500 { 519 abort_all_channels (plugins);
501 min_seek = pos->seek_request; 520 break;
502 } 521 }
503 } 522 }
504 } 523 /* if 'prp.file_finished', send 'abort' to plugins;
505 data_available = -1; 524 if not, send 'seek' notification to plugins in range */
506 if ( (1 == done) && 525 for (pos = plugins; NULL != pos; pos = pos->next)
507 (-1 != min_seek) && 526 {
508 (NULL != shm) ) 527 if (NULL == (channel = pos->channel))
509 { 528 {
510 /* current position done, but seek requested */ 529 /* Skipping plugin: channel down */
511 done = 0; 530 continue;
512 if (-1 == 531 }
513 (data_available = EXTRACTOR_IPC_shared_memory_set_ (shm, 532 if ( (-1 != pos->seek_request) &&
514 ds, 533 (1 == prp.file_finished) )
515 min_seek, 534 {
516 DEFAULT_SHM_SIZE))) 535 send_discard_message (pos);
517 { 536 pos->round_finished = 1;
518 LOG ("Failed to seek; full reset\n"); 537 pos->seek_request = -1;
519 abort_all_channels (plugins); 538 }
520 break; 539 if ( (-1 != data_available) &&
521 } 540 (-1 != pos->seek_request) &&
522 } 541 (min_seek <= pos->seek_request) &&
523 /* if 'prp.file_finished', send 'abort' to plugins; 542 ( (min_seek + data_available > pos->seek_request) ||
524 if not, send 'seek' notification to plugins in range */ 543 (min_seek == EXTRACTOR_datasource_get_size_ (ds, 0))) )
525 for (pos = plugins; NULL != pos; pos = pos->next) 544 {
526 { 545 /* Notify plugin about seek to 'min_seek' */
527 if (NULL == (channel = pos->channel)) 546 send_update_message (pos,
528 { 547 min_seek,
529 /* Skipping plugin: channel down */ 548 data_available,
530 continue; 549 ds);
531 } 550 pos->seek_request = -1;
532 if ( (-1 != pos->seek_request) && 551 }
533 (1 == prp.file_finished) ) 552 if (0 == pos->round_finished)
534 { 553 done = 0; /* can't be done, plugin still active */
535 send_discard_message (pos);
536 pos->round_finished = 1;
537 pos->seek_request = -1;
538 }
539 if ( (-1 != data_available) &&
540 (-1 != pos->seek_request) &&
541 (min_seek <= pos->seek_request) &&
542 ( (min_seek + data_available > pos->seek_request) ||
543 (min_seek == EXTRACTOR_datasource_get_size_ (ds, 0))) )
544 {
545 /* Notify plugin about seek to 'min_seek' */
546 send_update_message (pos,
547 min_seek,
548 data_available,
549 ds);
550 pos->seek_request = -1;
551 }
552 if (0 == pos->round_finished)
553 done = 0; /* can't be done, plugin still active */
554 }
555 } 554 }
555 }
556 556
557 if (0 == have_in_memory) 557 if (0 == have_in_memory)
558 return; 558 return;
@@ -567,22 +567,22 @@ do_extract (struct EXTRACTOR_PluginList *plugins,
567 ec.get_size = &in_process_get_size; 567 ec.get_size = &in_process_get_size;
568 ec.proc = &in_process_proc; 568 ec.proc = &in_process_proc;
569 for (pos = plugins; NULL != pos; pos = pos->next) 569 for (pos = plugins; NULL != pos; pos = pos->next)
570 {
571 if (EXTRACTOR_OPTION_IN_PROCESS != pos->flags)
572 continue;
573 if (-1 == EXTRACTOR_plugin_load_ (pos))
574 continue;
575 ctx.plugin = pos;
576 ec.config = pos->plugin_options;
577 if (-1 == EXTRACTOR_datasource_seek_ (ds, 0, SEEK_SET))
570 { 578 {
571 if (EXTRACTOR_OPTION_IN_PROCESS != pos->flags) 579 LOG ("Failed to seek to 0 for in-memory plugins\n");
572 continue; 580 return;
573 if (-1 == EXTRACTOR_plugin_load_ (pos))
574 continue;
575 ctx.plugin = pos;
576 ec.config = pos->plugin_options;
577 if (-1 == EXTRACTOR_datasource_seek_ (ds, 0, SEEK_SET))
578 {
579 LOG ("Failed to seek to 0 for in-memory plugins\n");
580 return;
581 }
582 pos->extract_method (&ec);
583 if (1 == ctx.finished)
584 break;
585 } 581 }
582 pos->extract_method (&ec);
583 if (1 == ctx.finished)
584 break;
585 }
586} 586}
587 587
588 588
@@ -602,11 +602,11 @@ do_extract (struct EXTRACTOR_PluginList *plugins,
602 */ 602 */
603void 603void
604EXTRACTOR_extract (struct EXTRACTOR_PluginList *plugins, 604EXTRACTOR_extract (struct EXTRACTOR_PluginList *plugins,
605 const char *filename, 605 const char *filename,
606 const void *data, 606 const void *data,
607 size_t size, 607 size_t size,
608 EXTRACTOR_MetaDataProcessor proc, 608 EXTRACTOR_MetaDataProcessor proc,
609 void *proc_cls) 609 void *proc_cls)
610{ 610{
611 struct EXTRACTOR_Datasource *datasource; 611 struct EXTRACTOR_Datasource *datasource;
612 struct EXTRACTOR_SharedMemory *shm; 612 struct EXTRACTOR_SharedMemory *shm;
@@ -617,47 +617,47 @@ EXTRACTOR_extract (struct EXTRACTOR_PluginList *plugins,
617 return; 617 return;
618 if (NULL == filename) 618 if (NULL == filename)
619 datasource = EXTRACTOR_datasource_create_from_buffer_ (data, size, 619 datasource = EXTRACTOR_datasource_create_from_buffer_ (data, size,
620 proc, proc_cls); 620 proc, proc_cls);
621 else 621 else
622 datasource = EXTRACTOR_datasource_create_from_file_ (filename, 622 datasource = EXTRACTOR_datasource_create_from_file_ (filename,
623 proc, proc_cls); 623 proc, proc_cls);
624 if (NULL == datasource) 624 if (NULL == datasource)
625 return; 625 return;
626 shm = NULL; 626 shm = NULL;
627 have_oop = 0; 627 have_oop = 0;
628 for (pos = plugins; NULL != pos; pos = pos->next) 628 for (pos = plugins; NULL != pos; pos = pos->next)
629 { 629 {
630 if (NULL == shm) 630 if (NULL == shm)
631 shm = pos->shm; 631 shm = pos->shm;
632 if (EXTRACTOR_OPTION_IN_PROCESS != pos->flags) 632 if (EXTRACTOR_OPTION_IN_PROCESS != pos->flags)
633 have_oop = 1; 633 have_oop = 1;
634 pos->round_finished = 0; 634 pos->round_finished = 0;
635 } 635 }
636 if ( (NULL == shm) && 636 if ( (NULL == shm) &&
637 (1 == have_oop) ) 637 (1 == have_oop) )
638 {
639 /* need to create shared memory segment */
640 shm = EXTRACTOR_IPC_shared_memory_create_ (DEFAULT_SHM_SIZE);
641 if (NULL == shm)
638 { 642 {
639 /* need to create shared memory segment */ 643 LOG ("Failed to setup IPC\n");
640 shm = EXTRACTOR_IPC_shared_memory_create_ (DEFAULT_SHM_SIZE); 644 EXTRACTOR_datasource_destroy_ (datasource);
641 if (NULL == shm) 645 return;
642 {
643 LOG ("Failed to setup IPC\n");
644 EXTRACTOR_datasource_destroy_ (datasource);
645 return;
646 }
647 } 646 }
647 }
648 for (pos = plugins; NULL != pos; pos = pos->next) 648 for (pos = plugins; NULL != pos; pos = pos->next)
649 if ( (NULL == pos->channel) && 649 if ( (NULL == pos->channel) &&
650 (NULL != shm) && 650 (NULL != shm) &&
651 (EXTRACTOR_OPTION_IN_PROCESS != pos->flags) ) 651 (EXTRACTOR_OPTION_IN_PROCESS != pos->flags) )
652 {
653 if (NULL == pos->shm)
652 { 654 {
653 if (NULL == pos->shm) 655 pos->shm = shm;
654 { 656 (void) EXTRACTOR_IPC_shared_memory_change_rc_ (shm, 1);
655 pos->shm = shm;
656 (void) EXTRACTOR_IPC_shared_memory_change_rc_ (shm, 1);
657 }
658 pos->channel = EXTRACTOR_IPC_channel_create_ (pos,
659 shm);
660 } 657 }
658 pos->channel = EXTRACTOR_IPC_channel_create_ (pos,
659 shm);
660 }
661 do_extract (plugins, 661 do_extract (plugins,
662 shm, 662 shm,
663 datasource, 663 datasource,
@@ -680,14 +680,14 @@ EXTRACTOR_ltdl_init ()
680#endif 680#endif
681 err = lt_dlinit (); 681 err = lt_dlinit ();
682 if (err > 0) 682 if (err > 0)
683 { 683 {
684#if DEBUG 684#if DEBUG
685 fprintf (stderr, 685 fprintf (stderr,
686 _("Initialization of plugin mechanism failed: %s!\n"), 686 _ ("Initialization of plugin mechanism failed: %s!\n"),
687 lt_dlerror ()); 687 lt_dlerror ());
688#endif 688#endif
689 return; 689 return;
690 } 690 }
691#if WINDOWS 691#if WINDOWS
692 plibc_init_utf8 ("GNU", PACKAGE, 1); 692 plibc_init_utf8 ("GNU", PACKAGE, 1);
693 plibc_set_stat_size_size (sizeof (((struct stat *) 0)->st_size)); 693 plibc_set_stat_size_size (sizeof (((struct stat *) 0)->st_size));
@@ -700,11 +700,13 @@ EXTRACTOR_ltdl_init ()
700 * Deinit. 700 * Deinit.
701 */ 701 */
702void __attribute__ ((destructor)) 702void __attribute__ ((destructor))
703EXTRACTOR_ltdl_fini () { 703EXTRACTOR_ltdl_fini ()
704{
704#if WINDOWS 705#if WINDOWS
705 plibc_shutdown (); 706 plibc_shutdown ();
706#endif 707#endif
707 lt_dlexit (); 708 lt_dlexit ();
708} 709}
709 710
711
710/* end of extractor.c */ 712/* end of extractor.c */
diff --git a/src/main/extractor_common.c b/src/main/extractor_common.c
index 866609e..59524b3 100644
--- a/src/main/extractor_common.c
+++ b/src/main/extractor_common.c
@@ -39,27 +39,27 @@
39 * @param buf buffer to read from 39 * @param buf buffer to read from
40 * @param size number of bytes to write 40 * @param size number of bytes to write
41 * @return number of bytes written (that is 'size'), or -1 on error 41 * @return number of bytes written (that is 'size'), or -1 on error
42 */ 42 */
43ssize_t 43ssize_t
44EXTRACTOR_write_all_ (int fd, 44EXTRACTOR_write_all_ (int fd,
45 const void *buf, 45 const void *buf,
46 size_t size) 46 size_t size)
47{ 47{
48 const char *data = buf; 48 const char *data = buf;
49 size_t off = 0; 49 size_t off = 0;
50 ssize_t ret; 50 ssize_t ret;
51 51
52 while (off < size) 52 while (off < size)
53 {
54 ret = write (fd, &data[off], size - off);
55 if (ret <= 0)
53 { 56 {
54 ret = write (fd, &data[off], size - off); 57 if (-1 == ret)
55 if (ret <= 0) 58 LOG_STRERROR ("write");
56 { 59 return -1;
57 if (-1 == ret)
58 LOG_STRERROR ("write");
59 return -1;
60 }
61 off += ret;
62 } 60 }
61 off += ret;
62 }
63 return size; 63 return size;
64} 64}
65 65
@@ -74,28 +74,27 @@ EXTRACTOR_write_all_ (int fd,
74 */ 74 */
75ssize_t 75ssize_t
76EXTRACTOR_read_all_ (int fd, 76EXTRACTOR_read_all_ (int fd,
77 void *buf, 77 void *buf,
78 size_t size) 78 size_t size)
79{ 79{
80 char *data = buf; 80 char *data = buf;
81 size_t off = 0; 81 size_t off = 0;
82 ssize_t ret; 82 ssize_t ret;
83 83
84 while (off < size) 84 while (off < size)
85 {
86 ret = read (fd, &data[off], size - off);
87 if (ret <= 0)
85 { 88 {
86 ret = read (fd, &data[off], size - off); 89 if (-1 == ret)
87 if (ret <= 0) 90 LOG_STRERROR ("write");
88 { 91 return -1;
89 if (-1 == ret)
90 LOG_STRERROR ("write");
91 return -1;
92 }
93 off += ret;
94 } 92 }
93 off += ret;
94 }
95 return size; 95 return size;
96
97}
98 96
97}
99 98
100 99
101/* end of extractor_common.c */ 100/* end of extractor_common.c */
diff --git a/src/main/extractor_common.h b/src/main/extractor_common.h
index 14b1c7f..5887c05 100644
--- a/src/main/extractor_common.h
+++ b/src/main/extractor_common.h
@@ -35,11 +35,11 @@
35 * @param buf buffer to read from 35 * @param buf buffer to read from
36 * @param size number of bytes to write 36 * @param size number of bytes to write
37 * @return number of bytes written (that is 'size'), or -1 on error 37 * @return number of bytes written (that is 'size'), or -1 on error
38 */ 38 */
39ssize_t 39ssize_t
40EXTRACTOR_write_all_ (int fd, 40EXTRACTOR_write_all_ (int fd,
41 const void *buf, 41 const void *buf,
42 size_t size); 42 size_t size);
43 43
44 44
45/** 45/**
@@ -52,8 +52,8 @@ EXTRACTOR_write_all_ (int fd,
52 */ 52 */
53ssize_t 53ssize_t
54EXTRACTOR_read_all_ (int fd, 54EXTRACTOR_read_all_ (int fd,
55 void *buf, 55 void *buf,
56 size_t size); 56 size_t size);
57 57
58 58
59#endif 59#endif
diff --git a/src/main/extractor_datasource.c b/src/main/extractor_datasource.c
index 888e524..0b18d7c 100644
--- a/src/main/extractor_datasource.c
+++ b/src/main/extractor_datasource.c
@@ -214,35 +214,35 @@ struct CompressedFileSource
214 */ 214 */
215static int 215static int
216bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds, 216bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds,
217 uint64_t pos) 217 uint64_t pos)
218{ 218{
219 int64_t position; 219 int64_t position;
220 ssize_t rd; 220 ssize_t rd;
221 221
222 if (pos > bfds->fsize) 222 if (pos > bfds->fsize)
223 { 223 {
224 LOG ("Invalid seek operation\n"); 224 LOG ("Invalid seek operation\n");
225 return -1; /* invalid */ 225 return -1; /* invalid */
226 } 226 }
227 if (NULL == bfds->buffer) 227 if (NULL == bfds->buffer)
228 { 228 {
229 bfds->buffer_pos = pos; 229 bfds->buffer_pos = pos;
230 return 0; 230 return 0;
231 } 231 }
232 position = (int64_t) LSEEK (bfds->fd, pos, SEEK_SET); 232 position = (int64_t) LSEEK (bfds->fd, pos, SEEK_SET);
233 if (position < 0) 233 if (position < 0)
234 { 234 {
235 LOG_STRERROR ("lseek"); 235 LOG_STRERROR ("lseek");
236 return -1; 236 return -1;
237 } 237 }
238 bfds->fpos = position; 238 bfds->fpos = position;
239 bfds->buffer_pos = 0; 239 bfds->buffer_pos = 0;
240 rd = read (bfds->fd, bfds->buffer, bfds->buffer_size); 240 rd = read (bfds->fd, bfds->buffer, bfds->buffer_size);
241 if (rd < 0) 241 if (rd < 0)
242 { 242 {
243 LOG_STRERROR ("read"); 243 LOG_STRERROR ("read");
244 return -1; 244 return -1;
245 } 245 }
246 bfds->buffer_bytes = rd; 246 bfds->buffer_bytes = rd;
247 return 0; 247 return 0;
248} 248}
@@ -258,8 +258,8 @@ bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds,
258 */ 258 */
259static struct BufferedFileDataSource * 259static struct BufferedFileDataSource *
260bfds_new (const void *data, 260bfds_new (const void *data,
261 int fd, 261 int fd,
262 int64_t fsize) 262 int64_t fsize)
263{ 263{
264 struct BufferedFileDataSource *result; 264 struct BufferedFileDataSource *result;
265 size_t xtra; 265 size_t xtra;
@@ -269,19 +269,19 @@ bfds_new (const void *data,
269 else 269 else
270 xtra = (size_t) fsize; 270 xtra = (size_t) fsize;
271 if ( (-1 == fd) && (NULL == data) ) 271 if ( (-1 == fd) && (NULL == data) )
272 { 272 {
273 LOG ("Invalid arguments\n"); 273 LOG ("Invalid arguments\n");
274 return NULL; 274 return NULL;
275 } 275 }
276 if ( (-1 != fd) && (NULL != data) ) 276 if ( (-1 != fd) && (NULL != data) )
277 fd = -1; /* don't need fd */ 277 fd = -1; /* don't need fd */
278 if (NULL != data) 278 if (NULL != data)
279 xtra = 0; 279 xtra = 0;
280 if (NULL == (result = malloc (sizeof (struct BufferedFileDataSource) + xtra))) 280 if (NULL == (result = malloc (sizeof (struct BufferedFileDataSource) + xtra)))
281 { 281 {
282 LOG_STRERROR ("malloc"); 282 LOG_STRERROR ("malloc");
283 return NULL; 283 return NULL;
284 } 284 }
285 memset (result, 0, sizeof (struct BufferedFileDataSource)); 285 memset (result, 0, sizeof (struct BufferedFileDataSource));
286 result->data = (NULL != data) ? data : &result[1]; 286 result->data = (NULL != data) ? data : &result[1];
287 result->buffer = (NULL != data) ? NULL : &result[1]; 287 result->buffer = (NULL != data) ? NULL : &result[1];
@@ -318,79 +318,79 @@ bfds_delete (struct BufferedFileDataSource *bfds)
318 */ 318 */
319static int64_t 319static int64_t
320bfds_seek (struct BufferedFileDataSource *bfds, 320bfds_seek (struct BufferedFileDataSource *bfds,
321 int64_t pos, int whence) 321 int64_t pos, int whence)
322{ 322{
323 uint64_t npos; 323 uint64_t npos;
324 size_t nbpos; 324 size_t nbpos;
325 325
326 switch (whence) 326 switch (whence)
327 {
328 case SEEK_CUR:
329 npos = bfds->fpos + bfds->buffer_pos + pos;
330 if (npos > bfds->fsize)
327 { 331 {
328 case SEEK_CUR: 332 LOG ("Invalid seek operation to %lld from %llu (max is %llu)\n",
329 npos = bfds->fpos + bfds->buffer_pos + pos; 333 (long long) pos,
330 if (npos > bfds->fsize) 334 bfds->fpos + bfds->buffer_pos,
331 { 335 (unsigned long long) bfds->fsize);
332 LOG ("Invalid seek operation to %lld from %llu (max is %llu)\n", 336 return -1;
333 (long long) pos, 337 }
334 bfds->fpos + bfds->buffer_pos, 338 nbpos = bfds->buffer_pos + pos;
335 (unsigned long long) bfds->fsize); 339 if ( (NULL == bfds->buffer) ||
336 return -1; 340 (nbpos < bfds->buffer_bytes) )
337 } 341 {
338 nbpos = bfds->buffer_pos + pos; 342 bfds->buffer_pos = nbpos;
339 if ( (NULL == bfds->buffer) ||
340 (nbpos < bfds->buffer_bytes) )
341 {
342 bfds->buffer_pos = nbpos;
343 return npos;
344 }
345 if (0 != bfds_pick_next_buffer_at (bfds,
346 npos))
347 {
348 LOG ("seek operation failed\n");
349 return -1;
350 }
351 return npos; 343 return npos;
352 case SEEK_END: 344 }
353 if (pos > 0) 345 if (0 != bfds_pick_next_buffer_at (bfds,
354 { 346 npos))
355 LOG ("Invalid seek operation\n"); 347 {
356 return -1; 348 LOG ("seek operation failed\n");
357 } 349 return -1;
358 if (bfds->fsize < - pos) 350 }
359 { 351 return npos;
360 LOG ("Invalid seek operation\n"); 352 case SEEK_END:
361 return -1; 353 if (pos > 0)
362 } 354 {
363 pos = bfds->fsize + pos; 355 LOG ("Invalid seek operation\n");
364 /* fall-through! */ 356 return -1;
365 case SEEK_SET: 357 }
366 if (pos < 0) 358 if (bfds->fsize < -pos)
367 { 359 {
368 LOG ("Invalid seek operation\n"); 360 LOG ("Invalid seek operation\n");
369 return -1; 361 return -1;
370 } 362 }
371 if (pos > bfds->fsize) 363 pos = bfds->fsize + pos;
372 { 364 /* fall-through! */
373 LOG ("Invalid seek operation (%lld > %llu) %d\n", 365 case SEEK_SET:
374 (long long) pos, 366 if (pos < 0)
375 (unsigned long long) bfds->fsize, 367 {
376 SEEK_SET == whence); 368 LOG ("Invalid seek operation\n");
377 return -1; 369 return -1;
378 } 370 }
379 if ( (NULL == bfds->buffer) || 371 if (pos > bfds->fsize)
380 ( (bfds->fpos <= pos) && 372 {
381 (bfds->fpos + bfds->buffer_bytes > pos) ) ) 373 LOG ("Invalid seek operation (%lld > %llu) %d\n",
382 { 374 (long long) pos,
383 bfds->buffer_pos = pos - bfds->fpos; 375 (unsigned long long) bfds->fsize,
384 return pos; 376 SEEK_SET == whence);
385 } 377 return -1;
386 if (0 != bfds_pick_next_buffer_at (bfds, pos)) 378 }
387 { 379 if ( (NULL == bfds->buffer) ||
388 LOG ("seek operation failed\n"); 380 ( (bfds->fpos <= pos) &&
389 return -1; 381 (bfds->fpos + bfds->buffer_bytes > pos) ) )
390 } 382 {
391 ASSERT (pos == bfds->fpos + bfds->buffer_pos); 383 bfds->buffer_pos = pos - bfds->fpos;
392 return pos; 384 return pos;
393 } 385 }
386 if (0 != bfds_pick_next_buffer_at (bfds, pos))
387 {
388 LOG ("seek operation failed\n");
389 return -1;
390 }
391 ASSERT (pos == bfds->fpos + bfds->buffer_pos);
392 return pos;
393 }
394 return -1; 394 return -1;
395} 395}
396 396
@@ -407,8 +407,8 @@ bfds_seek (struct BufferedFileDataSource *bfds,
407 */ 407 */
408static ssize_t 408static ssize_t
409bfds_read (struct BufferedFileDataSource *bfds, 409bfds_read (struct BufferedFileDataSource *bfds,
410 void *buf_ptr, 410 void *buf_ptr,
411 size_t count) 411 size_t count)
412{ 412{
413 char *cbuf = buf_ptr; 413 char *cbuf = buf_ptr;
414 uint64_t old_off; 414 uint64_t old_off;
@@ -420,28 +420,28 @@ bfds_read (struct BufferedFileDataSource *bfds,
420 return 0; /* end of stream */ 420 return 0; /* end of stream */
421 ret = 0; 421 ret = 0;
422 while (count > 0) 422 while (count > 0)
423 {
424 if ( (bfds->buffer_bytes == bfds->buffer_pos) &&
425 (0 != bfds_pick_next_buffer_at (bfds,
426 bfds->fpos + bfds->buffer_bytes)) )
423 { 427 {
424 if ( (bfds->buffer_bytes == bfds->buffer_pos) && 428 /* revert to original position, invalidate buffer */
425 (0 != bfds_pick_next_buffer_at (bfds, 429 bfds->fpos = old_off;
426 bfds->fpos + bfds->buffer_bytes)) ) 430 bfds->buffer_bytes = 0;
427 { 431 bfds->buffer_pos = 0;
428 /* revert to original position, invalidate buffer */ 432 LOG ("read operation failed\n");
429 bfds->fpos = old_off; 433 return -1; /* getting more failed */
430 bfds->buffer_bytes = 0;
431 bfds->buffer_pos = 0;
432 LOG ("read operation failed\n");
433 return -1; /* getting more failed */
434 }
435 avail = bfds->buffer_bytes - bfds->buffer_pos;
436 if (avail > count)
437 avail = count;
438 if (0 == avail)
439 break;
440 memcpy (&cbuf[ret], bfds->data + bfds->buffer_pos, avail);
441 bfds->buffer_pos += avail;
442 count -= avail;
443 ret += avail;
444 } 434 }
435 avail = bfds->buffer_bytes - bfds->buffer_pos;
436 if (avail > count)
437 avail = count;
438 if (0 == avail)
439 break;
440 memcpy (&cbuf[ret], bfds->data + bfds->buffer_pos, avail);
441 bfds->buffer_pos += avail;
442 count -= avail;
443 ret += avail;
444 }
445 return ret; 445 return ret;
446} 446}
447 447
@@ -458,17 +458,17 @@ bfds_read (struct BufferedFileDataSource *bfds,
458 */ 458 */
459static int 459static int
460cfs_init_decompressor_zlib (struct CompressedFileSource *cfs, 460cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
461 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 461 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
462{ 462{
463 unsigned int gzip_header_length = 10; 463 unsigned int gzip_header_length = 10;
464 unsigned char hdata[12]; 464 unsigned char hdata[12];
465 ssize_t rsize; 465 ssize_t rsize;
466 466
467 if (0 != bfds_seek (cfs->bfds, 0, SEEK_SET)) 467 if (0 != bfds_seek (cfs->bfds, 0, SEEK_SET))
468 { 468 {
469 LOG ("Failed to seek to offset 0!\n"); 469 LOG ("Failed to seek to offset 0!\n");
470 return -1; 470 return -1;
471 } 471 }
472 /* Process gzip header */ 472 /* Process gzip header */
473 rsize = bfds_read (cfs->bfds, hdata, sizeof (hdata)); 473 rsize = bfds_read (cfs->bfds, hdata, sizeof (hdata));
474 if ( (-1 == rsize) || 474 if ( (-1 == rsize) ||
@@ -478,72 +478,74 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
478 gzip_header_length += 2 + (hdata[10] & 0xff) + ((hdata[11] & 0xff) * 256); 478 gzip_header_length += 2 + (hdata[10] & 0xff) + ((hdata[11] & 0xff) * 256);
479 479
480 if (0 != (hdata[3] & 0x8)) 480 if (0 != (hdata[3] & 0x8))
481 {
482 /* FNAME set */
483 char fname[1024];
484 char *cptr;
485 size_t len;
486 ssize_t buf_bytes;
487
488 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
489 SEEK_SET))
481 { 490 {
482 /* FNAME set */ 491 LOG ("Corrupt gzip, failed to seek to end of header\n");
483 char fname[1024]; 492 return -1;
484 char *cptr;
485 size_t len;
486 ssize_t buf_bytes;
487
488 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length, SEEK_SET))
489 {
490 LOG ("Corrupt gzip, failed to seek to end of header\n");
491 return -1;
492 }
493 buf_bytes = bfds_read (cfs->bfds, fname, sizeof (fname));
494 if (buf_bytes <= 0)
495 {
496 LOG ("Corrupt gzip, failed to read filename\n");
497 return -1;
498 }
499 if (NULL == (cptr = memchr (fname, 0, buf_bytes)))
500 {
501 LOG ("Corrupt gzip, failed to read filename terminator\n");
502 return -1;
503 }
504 len = cptr - fname;
505 if ( (NULL != proc) &&
506 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
507 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
508 fname,
509 len)) )
510 return 0; /* done */
511 gzip_header_length += len + 1;
512 } 493 }
494 buf_bytes = bfds_read (cfs->bfds, fname, sizeof (fname));
495 if (buf_bytes <= 0)
496 {
497 LOG ("Corrupt gzip, failed to read filename\n");
498 return -1;
499 }
500 if (NULL == (cptr = memchr (fname, 0, buf_bytes)))
501 {
502 LOG ("Corrupt gzip, failed to read filename terminator\n");
503 return -1;
504 }
505 len = cptr - fname;
506 if ( (NULL != proc) &&
507 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
508 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
509 fname,
510 len)) )
511 return 0; /* done */
512 gzip_header_length += len + 1;
513 }
513 514
514 if (0 != (hdata[3] & 0x16)) 515 if (0 != (hdata[3] & 0x16))
516 {
517 /* FCOMMENT set */
518 char fcomment[1024];
519 char *cptr;
520 ssize_t buf_bytes;
521 size_t len;
522
523 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
524 SEEK_SET))
515 { 525 {
516 /* FCOMMENT set */ 526 LOG ("Corrupt gzip, failed to seek to end of header\n");
517 char fcomment[1024]; 527 return -1;
518 char *cptr; 528 }
519 ssize_t buf_bytes; 529 buf_bytes = bfds_read (cfs->bfds, fcomment, sizeof (fcomment));
520 size_t len; 530 if (buf_bytes <= 0)
521 531 {
522 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length, SEEK_SET)) 532 LOG ("Corrupt gzip, failed to read comment\n");
523 { 533 return -1;
524 LOG ("Corrupt gzip, failed to seek to end of header\n"); 534 }
525 return -1; 535 if (NULL == (cptr = memchr (fcomment, 0, buf_bytes)))
526 } 536 {
527 buf_bytes = bfds_read (cfs->bfds, fcomment, sizeof (fcomment)); 537 LOG ("Corrupt gzip, failed to read comment terminator\n");
528 if (buf_bytes <= 0) 538 return -1;
529 {
530 LOG ("Corrupt gzip, failed to read comment\n");
531 return -1;
532 }
533 if (NULL == (cptr = memchr (fcomment, 0, buf_bytes)))
534 {
535 LOG ("Corrupt gzip, failed to read comment terminator\n");
536 return -1;
537 }
538 len = cptr - fcomment;
539 if ( (NULL != proc) &&
540 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
541 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
542 (const char *) fcomment,
543 len)) )
544 return 0; /* done */
545 gzip_header_length += len + 1;
546 } 539 }
540 len = cptr - fcomment;
541 if ( (NULL != proc) &&
542 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
543 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
544 (const char *) fcomment,
545 len)) )
546 return 0; /* done */
547 gzip_header_length += len + 1;
548 }
547 if (0 != (hdata[3] & 0x2)) /* FCHRC set */ 549 if (0 != (hdata[3] & 0x2)) /* FCHRC set */
548 gzip_header_length += 2; 550 gzip_header_length += 2;
549 memset (&cfs->strm, 0, sizeof (z_stream)); 551 memset (&cfs->strm, 0, sizeof (z_stream));
@@ -556,10 +558,10 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
556 558
557 if (cfs->gzip_header_length != 559 if (cfs->gzip_header_length !=
558 bfds_seek (cfs->bfds, cfs->gzip_header_length, SEEK_SET)) 560 bfds_seek (cfs->bfds, cfs->gzip_header_length, SEEK_SET))
559 { 561 {
560 LOG ("Failed to seek to start to initialize gzip decompressor\n"); 562 LOG ("Failed to seek to start to initialize gzip decompressor\n");
561 return -1; 563 return -1;
562 } 564 }
563 cfs->strm.avail_out = COM_CHUNK_SIZE; 565 cfs->strm.avail_out = COM_CHUNK_SIZE;
564 /* 566 /*
565 * note: maybe plain inflateInit(&strm) is adequate, 567 * note: maybe plain inflateInit(&strm) is adequate,
@@ -567,20 +569,21 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
567 * 569 *
568 * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ; 570 * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ;
569 * there might be a better check. 571 * there might be a better check.
570 */ 572 */if (Z_OK != inflateInit2 (&cfs->strm,
571 if (Z_OK != inflateInit2 (&cfs->strm,
572#ifdef ZLIB_VERNUM 573#ifdef ZLIB_VERNUM
573 15 + 32 574 15 + 32
574#else 575#else
575 - MAX_WBITS 576 -MAX_WBITS
576#endif 577#endif
577 )) 578 ))
578 { 579 {
579 LOG ("Failed to initialize zlib decompression\n"); 580 LOG ("Failed to initialize zlib decompression\n");
580 return -1; 581 return -1;
581 } 582 }
582 return 1; 583 return 1;
583} 584}
585
586
584#endif 587#endif
585 588
586 589
@@ -596,24 +599,26 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
596 */ 599 */
597static int 600static int
598cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs, 601cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
599 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 602 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
600{ 603{
601 if (0 != 604 if (0 !=
602 bfds_seek (cfs->bfds, 0, SEEK_SET)) 605 bfds_seek (cfs->bfds, 0, SEEK_SET))
603 { 606 {
604 LOG ("Failed to seek to start to initialize BZ2 decompressor\n"); 607 LOG ("Failed to seek to start to initialize BZ2 decompressor\n");
605 return -1; 608 return -1;
606 } 609 }
607 memset (&cfs->bstrm, 0, sizeof (bz_stream)); 610 memset (&cfs->bstrm, 0, sizeof (bz_stream));
608 if (BZ_OK != 611 if (BZ_OK !=
609 BZ2_bzDecompressInit (&cfs->bstrm, 0, 0)) 612 BZ2_bzDecompressInit (&cfs->bstrm, 0, 0))
610 { 613 {
611 LOG ("Failed to initialize BZ2 decompressor\n"); 614 LOG ("Failed to initialize BZ2 decompressor\n");
612 return -1; 615 return -1;
613 } 616 }
614 cfs->bstrm.avail_out = COM_CHUNK_SIZE; 617 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
615 return 1; 618 return 1;
616} 619}
620
621
617#endif 622#endif
618 623
619 624
@@ -628,24 +633,24 @@ cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
628 */ 633 */
629static int 634static int
630cfs_init_decompressor (struct CompressedFileSource *cfs, 635cfs_init_decompressor (struct CompressedFileSource *cfs,
631 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 636 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
632{ 637{
633 cfs->result_pos = 0; 638 cfs->result_pos = 0;
634 cfs->fpos = 0; 639 cfs->fpos = 0;
635 switch (cfs->compression_type) 640 switch (cfs->compression_type)
636 { 641 {
637#if HAVE_ZLIB 642#if HAVE_ZLIB
638 case COMP_TYPE_ZLIB: 643 case COMP_TYPE_ZLIB:
639 return cfs_init_decompressor_zlib (cfs, proc, proc_cls); 644 return cfs_init_decompressor_zlib (cfs, proc, proc_cls);
640#endif 645#endif
641#if HAVE_LIBBZ2 646#if HAVE_LIBBZ2
642 case COMP_TYPE_BZ2: 647 case COMP_TYPE_BZ2:
643 return cfs_init_decompressor_bz2 (cfs, proc, proc_cls); 648 return cfs_init_decompressor_bz2 (cfs, proc, proc_cls);
644#endif 649#endif
645 default: 650 default:
646 LOG ("invalid compression type selected\n"); 651 LOG ("invalid compression type selected\n");
647 return -1; 652 return -1;
648 } 653 }
649} 654}
650 655
651 656
@@ -662,6 +667,8 @@ cfs_deinit_decompressor_zlib (struct CompressedFileSource *cfs)
662 inflateEnd (&cfs->strm); 667 inflateEnd (&cfs->strm);
663 return 1; 668 return 1;
664} 669}
670
671
665#endif 672#endif
666 673
667 674
@@ -678,6 +685,8 @@ cfs_deinit_decompressor_bz2 (struct CompressedFileSource *cfs)
678 BZ2_bzDecompressEnd (&cfs->bstrm); 685 BZ2_bzDecompressEnd (&cfs->bstrm);
679 return 1; 686 return 1;
680} 687}
688
689
681#endif 690#endif
682 691
683 692
@@ -691,19 +700,19 @@ static int
691cfs_deinit_decompressor (struct CompressedFileSource *cfs) 700cfs_deinit_decompressor (struct CompressedFileSource *cfs)
692{ 701{
693 switch (cfs->compression_type) 702 switch (cfs->compression_type)
694 { 703 {
695#if HAVE_ZLIB 704#if HAVE_ZLIB
696 case COMP_TYPE_ZLIB: 705 case COMP_TYPE_ZLIB:
697 return cfs_deinit_decompressor_zlib (cfs); 706 return cfs_deinit_decompressor_zlib (cfs);
698#endif 707#endif
699#if HAVE_LIBBZ2 708#if HAVE_LIBBZ2
700 case COMP_TYPE_BZ2: 709 case COMP_TYPE_BZ2:
701 return cfs_deinit_decompressor_bz2 (cfs); 710 return cfs_deinit_decompressor_bz2 (cfs);
702#endif 711#endif
703 default: 712 default:
704 LOG ("invalid compression type selected\n"); 713 LOG ("invalid compression type selected\n");
705 return -1; 714 return -1;
706 } 715 }
707} 716}
708 717
709 718
@@ -750,28 +759,28 @@ cfs_destroy (struct CompressedFileSource *cfs)
750 */ 759 */
751struct CompressedFileSource * 760struct CompressedFileSource *
752cfs_new (struct BufferedFileDataSource *bfds, 761cfs_new (struct BufferedFileDataSource *bfds,
753 int64_t fsize, 762 int64_t fsize,
754 enum ExtractorCompressionType compression_type, 763 enum ExtractorCompressionType compression_type,
755 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 764 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
756{ 765{
757 struct CompressedFileSource *cfs; 766 struct CompressedFileSource *cfs;
758 767
759 if (NULL == (cfs = malloc (sizeof (struct CompressedFileSource)))) 768 if (NULL == (cfs = malloc (sizeof (struct CompressedFileSource))))
760 { 769 {
761 LOG_STRERROR ("malloc"); 770 LOG_STRERROR ("malloc");
762 return NULL; 771 return NULL;
763 } 772 }
764 memset (cfs, 0, sizeof (struct CompressedFileSource)); 773 memset (cfs, 0, sizeof (struct CompressedFileSource));
765 cfs->compression_type = compression_type; 774 cfs->compression_type = compression_type;
766 cfs->bfds = bfds; 775 cfs->bfds = bfds;
767 cfs->fsize = fsize; 776 cfs->fsize = fsize;
768 cfs->uncompressed_size = -1; 777 cfs->uncompressed_size = -1;
769 if (1 != cfs_init_decompressor (cfs, 778 if (1 != cfs_init_decompressor (cfs,
770 proc, proc_cls)) 779 proc, proc_cls))
771 { 780 {
772 free (cfs); 781 free (cfs);
773 return NULL; 782 return NULL;
774 } 783 }
775 return cfs; 784 return cfs;
776} 785}
777 786
@@ -789,8 +798,8 @@ cfs_new (struct BufferedFileDataSource *bfds,
789 */ 798 */
790static ssize_t 799static ssize_t
791cfs_read_zlib (struct CompressedFileSource *cfs, 800cfs_read_zlib (struct CompressedFileSource *cfs,
792 void *data, 801 void *data,
793 size_t size) 802 size_t size)
794{ 803{
795 char *dst = data; 804 char *dst = data;
796 int ret; 805 int ret;
@@ -799,77 +808,79 @@ cfs_read_zlib (struct CompressedFileSource *cfs,
799 unsigned char buf[COM_CHUNK_SIZE]; 808 unsigned char buf[COM_CHUNK_SIZE];
800 809
801 if (cfs->fpos == cfs->uncompressed_size) 810 if (cfs->fpos == cfs->uncompressed_size)
802 { 811 {
803 /* end of file */ 812 /* end of file */
804 return 0; 813 return 0;
805 } 814 }
806 rc = 0; 815 rc = 0;
807 if (COM_CHUNK_SIZE > cfs->strm.avail_out + cfs->result_pos) 816 if (COM_CHUNK_SIZE > cfs->strm.avail_out + cfs->result_pos)
808 { 817 {
809 /* got left-over decompressed data from previous round! */ 818 /* got left-over decompressed data from previous round! */
810 in = COM_CHUNK_SIZE - (cfs->strm.avail_out + cfs->result_pos); 819 in = COM_CHUNK_SIZE - (cfs->strm.avail_out + cfs->result_pos);
811 if (in > size) 820 if (in > size)
812 in = size; 821 in = size;
813 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in); 822 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
814 cfs->fpos += in; 823 cfs->fpos += in;
815 cfs->result_pos += in; 824 cfs->result_pos += in;
816 rc += in; 825 rc += in;
817 } 826 }
818 ret = Z_OK; 827 ret = Z_OK;
819 while ( (rc < size) && (Z_STREAM_END != ret) ) 828 while ( (rc < size) && (Z_STREAM_END != ret) )
829 {
830 /* read block from original data source */
831 in = bfds_read (cfs->bfds,
832 buf, sizeof (buf));
833 if (in < 0)
820 { 834 {
821 /* read block from original data source */ 835 LOG ("unexpected EOF\n");
822 in = bfds_read (cfs->bfds, 836 return -1; /* unexpected EOF */
823 buf, sizeof (buf));
824 if (in < 0)
825 {
826 LOG ("unexpected EOF\n");
827 return -1; /* unexpected EOF */
828 }
829 if (0 == in)
830 {
831 cfs->uncompressed_size = cfs->fpos;
832 return rc;
833 }
834 cfs->strm.next_in = buf;
835 cfs->strm.avail_in = (uInt) in;
836 cfs->strm.next_out = (unsigned char *) cfs->result;
837 cfs->strm.avail_out = COM_CHUNK_SIZE;
838 cfs->result_pos = 0;
839 ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
840 if ( (Z_OK != ret) && (Z_STREAM_END != ret) )
841 {
842 LOG ("unexpected gzip inflate error: %d\n", ret);
843 return -1; /* unexpected error */
844 }
845 /* go backwards by the number of bytes left in the buffer */
846 if (-1 == bfds_seek (cfs->bfds, - (int64_t) cfs->strm.avail_in, SEEK_CUR))
847 {
848 LOG ("seek failed\n");
849 return -1;
850 }
851 /* copy decompressed bytes to target buffer */
852 in = COM_CHUNK_SIZE - cfs->strm.avail_out;
853 if (in > size - rc)
854 {
855 if (Z_STREAM_END == ret)
856 {
857 cfs->uncompressed_size = cfs->fpos + in;
858 ret = Z_OK;
859 }
860 in = size - rc;
861 }
862 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
863 cfs->fpos += in;
864 cfs->result_pos += in;
865 rc += in;
866 } 837 }
867 if (Z_STREAM_END == ret) 838 if (0 == in)
868 { 839 {
869 cfs->uncompressed_size = cfs->fpos; 840 cfs->uncompressed_size = cfs->fpos;
841 return rc;
842 }
843 cfs->strm.next_in = buf;
844 cfs->strm.avail_in = (uInt) in;
845 cfs->strm.next_out = (unsigned char *) cfs->result;
846 cfs->strm.avail_out = COM_CHUNK_SIZE;
847 cfs->result_pos = 0;
848 ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
849 if ( (Z_OK != ret) && (Z_STREAM_END != ret) )
850 {
851 LOG ("unexpected gzip inflate error: %d\n", ret);
852 return -1; /* unexpected error */
853 }
854 /* go backwards by the number of bytes left in the buffer */
855 if (-1 == bfds_seek (cfs->bfds, -(int64_t) cfs->strm.avail_in, SEEK_CUR))
856 {
857 LOG ("seek failed\n");
858 return -1;
859 }
860 /* copy decompressed bytes to target buffer */
861 in = COM_CHUNK_SIZE - cfs->strm.avail_out;
862 if (in > size - rc)
863 {
864 if (Z_STREAM_END == ret)
865 {
866 cfs->uncompressed_size = cfs->fpos + in;
867 ret = Z_OK;
868 }
869 in = size - rc;
870 } 870 }
871 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
872 cfs->fpos += in;
873 cfs->result_pos += in;
874 rc += in;
875 }
876 if (Z_STREAM_END == ret)
877 {
878 cfs->uncompressed_size = cfs->fpos;
879 }
871 return rc; 880 return rc;
872} 881}
882
883
873#endif 884#endif
874 885
875 886
@@ -886,8 +897,8 @@ cfs_read_zlib (struct CompressedFileSource *cfs,
886 */ 897 */
887static ssize_t 898static ssize_t
888cfs_read_bz2 (struct CompressedFileSource *cfs, 899cfs_read_bz2 (struct CompressedFileSource *cfs,
889 void *data, 900 void *data,
890 size_t size) 901 size_t size)
891{ 902{
892 char *dst = data; 903 char *dst = data;
893 int ret; 904 int ret;
@@ -896,77 +907,79 @@ cfs_read_bz2 (struct CompressedFileSource *cfs,
896 char buf[COM_CHUNK_SIZE]; 907 char buf[COM_CHUNK_SIZE];
897 908
898 if (cfs->fpos == cfs->uncompressed_size) 909 if (cfs->fpos == cfs->uncompressed_size)
899 { 910 {
900 /* end of file */ 911 /* end of file */
901 return 0; 912 return 0;
902 } 913 }
903 rc = 0; 914 rc = 0;
904 if (COM_CHUNK_SIZE > cfs->bstrm.avail_out + cfs->result_pos) 915 if (COM_CHUNK_SIZE > cfs->bstrm.avail_out + cfs->result_pos)
905 { 916 {
906 /* got left-over decompressed data from previous round! */ 917 /* got left-over decompressed data from previous round! */
907 in = COM_CHUNK_SIZE - (cfs->bstrm.avail_out + cfs->result_pos); 918 in = COM_CHUNK_SIZE - (cfs->bstrm.avail_out + cfs->result_pos);
908 if (in > size) 919 if (in > size)
909 in = size; 920 in = size;
910 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in); 921 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
911 cfs->fpos += in; 922 cfs->fpos += in;
912 cfs->result_pos += in; 923 cfs->result_pos += in;
913 rc += in; 924 rc += in;
914 } 925 }
915 ret = BZ_OK; 926 ret = BZ_OK;
916 while ( (rc < size) && (BZ_STREAM_END != ret) ) 927 while ( (rc < size) && (BZ_STREAM_END != ret) )
928 {
929 /* read block from original data source */
930 in = bfds_read (cfs->bfds,
931 buf, sizeof (buf));
932 if (in < 0)
917 { 933 {
918 /* read block from original data source */ 934 LOG ("unexpected EOF\n");
919 in = bfds_read (cfs->bfds, 935 return -1; /* unexpected EOF */
920 buf, sizeof (buf));
921 if (in < 0)
922 {
923 LOG ("unexpected EOF\n");
924 return -1; /* unexpected EOF */
925 }
926 if (0 == in)
927 {
928 cfs->uncompressed_size = cfs->fpos;
929 return rc;
930 }
931 cfs->bstrm.next_in = buf;
932 cfs->bstrm.avail_in = (unsigned int) in;
933 cfs->bstrm.next_out = cfs->result;
934 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
935 cfs->result_pos = 0;
936 ret = BZ2_bzDecompress (&cfs->bstrm);
937 if ( (BZ_OK != ret) && (BZ_STREAM_END != ret) )
938 {
939 LOG ("unexpected bzip2 decompress error: %d\n", ret);
940 return -1; /* unexpected error */
941 }
942 /* go backwards by the number of bytes left in the buffer */
943 if (-1 == bfds_seek (cfs->bfds, - (int64_t) cfs->bstrm.avail_in, SEEK_CUR))
944 {
945 LOG ("seek failed\n");
946 return -1;
947 }
948 /* copy decompressed bytes to target buffer */
949 in = COM_CHUNK_SIZE - cfs->bstrm.avail_out;
950 if (in > size - rc)
951 {
952 if (BZ_STREAM_END == ret)
953 {
954 cfs->uncompressed_size = cfs->fpos + in;
955 ret = BZ_OK;
956 }
957 in = size - rc;
958 }
959 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
960 cfs->fpos += in;
961 cfs->result_pos += in;
962 rc += in;
963 } 936 }
964 if (BZ_STREAM_END == ret) 937 if (0 == in)
965 { 938 {
966 cfs->uncompressed_size = cfs->fpos; 939 cfs->uncompressed_size = cfs->fpos;
940 return rc;
941 }
942 cfs->bstrm.next_in = buf;
943 cfs->bstrm.avail_in = (unsigned int) in;
944 cfs->bstrm.next_out = cfs->result;
945 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
946 cfs->result_pos = 0;
947 ret = BZ2_bzDecompress (&cfs->bstrm);
948 if ( (BZ_OK != ret) && (BZ_STREAM_END != ret) )
949 {
950 LOG ("unexpected bzip2 decompress error: %d\n", ret);
951 return -1; /* unexpected error */
952 }
953 /* go backwards by the number of bytes left in the buffer */
954 if (-1 == bfds_seek (cfs->bfds, -(int64_t) cfs->bstrm.avail_in, SEEK_CUR))
955 {
956 LOG ("seek failed\n");
957 return -1;
967 } 958 }
959 /* copy decompressed bytes to target buffer */
960 in = COM_CHUNK_SIZE - cfs->bstrm.avail_out;
961 if (in > size - rc)
962 {
963 if (BZ_STREAM_END == ret)
964 {
965 cfs->uncompressed_size = cfs->fpos + in;
966 ret = BZ_OK;
967 }
968 in = size - rc;
969 }
970 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
971 cfs->fpos += in;
972 cfs->result_pos += in;
973 rc += in;
974 }
975 if (BZ_STREAM_END == ret)
976 {
977 cfs->uncompressed_size = cfs->fpos;
978 }
968 return rc; 979 return rc;
969} 980}
981
982
970#endif 983#endif
971 984
972 985
@@ -982,23 +995,23 @@ cfs_read_bz2 (struct CompressedFileSource *cfs,
982 */ 995 */
983static ssize_t 996static ssize_t
984cfs_read (struct CompressedFileSource *cfs, 997cfs_read (struct CompressedFileSource *cfs,
985 void *data, 998 void *data,
986 size_t size) 999 size_t size)
987{ 1000{
988 switch (cfs->compression_type) 1001 switch (cfs->compression_type)
989 { 1002 {
990#if HAVE_ZLIB 1003#if HAVE_ZLIB
991 case COMP_TYPE_ZLIB: 1004 case COMP_TYPE_ZLIB:
992 return cfs_read_zlib (cfs, data, size); 1005 return cfs_read_zlib (cfs, data, size);
993#endif 1006#endif
994#if HAVE_LIBBZ2 1007#if HAVE_LIBBZ2
995 case COMP_TYPE_BZ2: 1008 case COMP_TYPE_BZ2:
996 return cfs_read_bz2 (cfs, data, size); 1009 return cfs_read_bz2 (cfs, data, size);
997#endif 1010#endif
998 default: 1011 default:
999 LOG ("invalid compression type selected\n"); 1012 LOG ("invalid compression type selected\n");
1000 return -1; 1013 return -1;
1001 } 1014 }
1002} 1015}
1003 1016
1004 1017
@@ -1014,104 +1027,105 @@ cfs_read (struct CompressedFileSource *cfs,
1014 */ 1027 */
1015static int64_t 1028static int64_t
1016cfs_seek (struct CompressedFileSource *cfs, 1029cfs_seek (struct CompressedFileSource *cfs,
1017 int64_t position, 1030 int64_t position,
1018 int whence) 1031 int whence)
1019{ 1032{
1020 uint64_t nposition; 1033 uint64_t nposition;
1021 int64_t delta; 1034 int64_t delta;
1022 1035
1023 switch (whence) 1036 switch (whence)
1037 {
1038 case SEEK_CUR:
1039 if (cfs->fpos + position < 0)
1040 {
1041 /* underflow */
1042 LOG ("Invalid seek operation\n");
1043 return -1;
1044 }
1045 if ( (-1 != cfs->uncompressed_size) &&
1046 (cfs->fpos + position > cfs->uncompressed_size) )
1047 {
1048 LOG ("Invalid seek operation\n");
1049 return -1;
1050 }
1051 nposition = cfs->fpos + position;
1052 break;
1053 case SEEK_END:
1054 ASSERT (-1 != cfs->uncompressed_size);
1055 if (position > 0)
1024 { 1056 {
1025 case SEEK_CUR:
1026 if (cfs->fpos + position < 0)
1027 {
1028 /* underflow */
1029 LOG ("Invalid seek operation\n");
1030 return -1;
1031 }
1032 if ( (-1 != cfs->uncompressed_size) &&
1033 (cfs->fpos + position > cfs->uncompressed_size) )
1034 {
1035 LOG ("Invalid seek operation\n");
1036 return -1;
1037 }
1038 nposition = cfs->fpos + position;
1039 break;
1040 case SEEK_END:
1041 ASSERT (-1 != cfs->uncompressed_size);
1042 if (position > 0)
1043 {
1044 LOG ("Invalid seek operation\n");
1045 return -1;
1046 }
1047 if (cfs->uncompressed_size < - position)
1048 {
1049 LOG ("Invalid seek operation\n");
1050 return -1;
1051 }
1052 nposition = cfs->uncompressed_size + position;
1053 break;
1054 case SEEK_SET:
1055 if (position < 0)
1056 {
1057 LOG ("Invalid seek operation\n");
1058 return -1;
1059 }
1060 if ( (-1 != cfs->uncompressed_size) &&
1061 (cfs->uncompressed_size < position ) )
1062 {
1063 LOG ("Invalid seek operation\n");
1064 return -1;
1065 }
1066 nposition = (uint64_t) position;
1067 break;
1068 default:
1069 LOG ("Invalid seek operation\n"); 1057 LOG ("Invalid seek operation\n");
1070 return -1; 1058 return -1;
1071 } 1059 }
1060 if (cfs->uncompressed_size < -position)
1061 {
1062 LOG ("Invalid seek operation\n");
1063 return -1;
1064 }
1065 nposition = cfs->uncompressed_size + position;
1066 break;
1067 case SEEK_SET:
1068 if (position < 0)
1069 {
1070 LOG ("Invalid seek operation\n");
1071 return -1;
1072 }
1073 if ( (-1 != cfs->uncompressed_size) &&
1074 (cfs->uncompressed_size < position) )
1075 {
1076 LOG ("Invalid seek operation\n");
1077 return -1;
1078 }
1079 nposition = (uint64_t) position;
1080 break;
1081 default:
1082 LOG ("Invalid seek operation\n");
1083 return -1;
1084 }
1072 delta = nposition - cfs->fpos; 1085 delta = nposition - cfs->fpos;
1073 if (delta < 0) 1086 if (delta < 0)
1087 {
1088 if (cfs->result_pos >= -delta)
1074 { 1089 {
1075 if (cfs->result_pos >= - delta) 1090 cfs->result_pos += delta;
1076 { 1091 cfs->fpos += delta;
1077 cfs->result_pos += delta; 1092 delta = 0;
1078 cfs->fpos += delta;
1079 delta = 0;
1080 }
1081 else
1082 {
1083 if (-1 == cfs_reset_stream (cfs))
1084 {
1085 LOG ("Failed to restart compressed stream for seek operation\n");
1086 return -1;
1087 }
1088 delta = nposition;
1089 }
1090 } 1093 }
1094 else
1095 {
1096 if (-1 == cfs_reset_stream (cfs))
1097 {
1098 LOG ("Failed to restart compressed stream for seek operation\n");
1099 return -1;
1100 }
1101 delta = nposition;
1102 }
1103 }
1091 while (delta > 0) 1104 while (delta > 0)
1105 {
1106 char buf[COM_CHUNK_SIZE];
1107 size_t max;
1108 int64_t ret;
1109
1110 max = (sizeof (buf) > delta) ? delta : sizeof (buf);
1111 ret = cfs_read (cfs, buf, max);
1112 if (-1 == ret)
1113 {
1114 LOG ("Failed to read decompressed stream for seek operation\n");
1115 return -1;
1116 }
1117 if (0 == ret)
1092 { 1118 {
1093 char buf[COM_CHUNK_SIZE]; 1119 LOG (
1094 size_t max; 1120 "Reached unexpected end of stream at %llu during seek operation to %llu (%d left)\n",
1095 int64_t ret; 1121 (unsigned long long) cfs->fpos,
1096 1122 (unsigned long long) nposition,
1097 max = (sizeof (buf) > delta) ? delta : sizeof (buf); 1123 delta);
1098 ret = cfs_read (cfs, buf, max); 1124 return -1;
1099 if (-1 == ret)
1100 {
1101 LOG ("Failed to read decompressed stream for seek operation\n");
1102 return -1;
1103 }
1104 if (0 == ret)
1105 {
1106 LOG ("Reached unexpected end of stream at %llu during seek operation to %llu (%d left)\n",
1107 (unsigned long long) cfs->fpos,
1108 (unsigned long long) nposition,
1109 delta);
1110 return -1;
1111 }
1112 ASSERT (ret <= delta);
1113 delta -= ret;
1114 } 1125 }
1126 ASSERT (ret <= delta);
1127 delta -= ret;
1128 }
1115 return cfs->fpos; 1129 return cfs->fpos;
1116} 1130}
1117 1131
@@ -1186,8 +1200,8 @@ struct EXTRACTOR_Datasource
1186 */ 1200 */
1187struct EXTRACTOR_Datasource * 1201struct EXTRACTOR_Datasource *
1188EXTRACTOR_datasource_create_from_file_ (const char *filename, 1202EXTRACTOR_datasource_create_from_file_ (const char *filename,
1189 EXTRACTOR_MetaDataProcessor proc, 1203 EXTRACTOR_MetaDataProcessor proc,
1190 void *proc_cls) 1204 void *proc_cls)
1191{ 1205{
1192 struct BufferedFileDataSource *bfds; 1206 struct BufferedFileDataSource *bfds;
1193 struct EXTRACTOR_Datasource *ds; 1207 struct EXTRACTOR_Datasource *ds;
@@ -1201,56 +1215,56 @@ EXTRACTOR_datasource_create_from_file_ (const char *filename,
1201#endif 1215#endif
1202 1216
1203 if (-1 == (fd = OPEN (filename, O_RDONLY | O_LARGEFILE | winmode))) 1217 if (-1 == (fd = OPEN (filename, O_RDONLY | O_LARGEFILE | winmode)))
1204 { 1218 {
1205 LOG_STRERROR_FILE ("open", filename); 1219 LOG_STRERROR_FILE ("open", filename);
1206 return NULL; 1220 return NULL;
1207 } 1221 }
1208 if ( (0 != FSTAT (fd, &sb)) || 1222 if ( (0 != FSTAT (fd, &sb)) ||
1209 (S_ISDIR (sb.st_mode)) ) 1223 (S_ISDIR (sb.st_mode)) )
1210 { 1224 {
1211 if (! S_ISDIR (sb.st_mode)) 1225 if (! S_ISDIR (sb.st_mode))
1212 LOG_STRERROR_FILE ("fstat", filename); 1226 LOG_STRERROR_FILE ("fstat", filename);
1213 else 1227 else
1214 LOG ("Skipping directory `%s'\n", filename); 1228 LOG ("Skipping directory `%s'\n", filename);
1215 (void) CLOSE (fd); 1229 (void) CLOSE (fd);
1216 return NULL; 1230 return NULL;
1217 } 1231 }
1218 fsize = (int64_t) sb.st_size; 1232 fsize = (int64_t) sb.st_size;
1219 if (0 == fsize) 1233 if (0 == fsize)
1220 { 1234 {
1221 (void) CLOSE (fd); 1235 (void) CLOSE (fd);
1222 return NULL; 1236 return NULL;
1223 } 1237 }
1224 bfds = bfds_new (NULL, fd, fsize); 1238 bfds = bfds_new (NULL, fd, fsize);
1225 if (NULL == bfds) 1239 if (NULL == bfds)
1226 { 1240 {
1227 (void) CLOSE (fd); 1241 (void) CLOSE (fd);
1228 return NULL; 1242 return NULL;
1229 } 1243 }
1230 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource)))) 1244 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource))))
1231 { 1245 {
1232 LOG_STRERROR ("malloc"); 1246 LOG_STRERROR ("malloc");
1233 bfds_delete (bfds); 1247 bfds_delete (bfds);
1234 (void) CLOSE (fd); 1248 (void) CLOSE (fd);
1235 return NULL; 1249 return NULL;
1236 } 1250 }
1237 ds->bfds = bfds; 1251 ds->bfds = bfds;
1238 ds->fd = fd; 1252 ds->fd = fd;
1239 ds->cfs = NULL; 1253 ds->cfs = NULL;
1240 ct = get_compression_type (bfds); 1254 ct = get_compression_type (bfds);
1241 if ( (COMP_TYPE_ZLIB == ct) || 1255 if ( (COMP_TYPE_ZLIB == ct) ||
1242 (COMP_TYPE_BZ2 == ct) ) 1256 (COMP_TYPE_BZ2 == ct) )
1257 {
1258 ds->cfs = cfs_new (bfds, fsize, ct, proc, proc_cls);
1259 if (NULL == ds->cfs)
1243 { 1260 {
1244 ds->cfs = cfs_new (bfds, fsize, ct, proc, proc_cls); 1261 LOG ("Failed to initialize decompressor\n");
1245 if (NULL == ds->cfs) 1262 bfds_delete (bfds);
1246 { 1263 free (ds);
1247 LOG ("Failed to initialize decompressor\n"); 1264 (void) CLOSE (fd);
1248 bfds_delete (bfds); 1265 return NULL;
1249 free (ds);
1250 (void) CLOSE (fd);
1251 return NULL;
1252 }
1253 } 1266 }
1267 }
1254 return ds; 1268 return ds;
1255} 1269}
1256 1270
@@ -1266,8 +1280,9 @@ EXTRACTOR_datasource_create_from_file_ (const char *filename,
1266 */ 1280 */
1267struct EXTRACTOR_Datasource * 1281struct EXTRACTOR_Datasource *
1268EXTRACTOR_datasource_create_from_buffer_ (const char *buf, 1282EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
1269 size_t size, 1283 size_t size,
1270 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 1284 EXTRACTOR_MetaDataProcessor proc,
1285 void *proc_cls)
1271{ 1286{
1272 struct BufferedFileDataSource *bfds; 1287 struct BufferedFileDataSource *bfds;
1273 struct EXTRACTOR_Datasource *ds; 1288 struct EXTRACTOR_Datasource *ds;
@@ -1276,32 +1291,32 @@ EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
1276 if (0 == size) 1291 if (0 == size)
1277 return NULL; 1292 return NULL;
1278 if (NULL == (bfds = bfds_new (buf, -1, size))) 1293 if (NULL == (bfds = bfds_new (buf, -1, size)))
1279 { 1294 {
1280 LOG ("Failed to initialize buffer data source\n"); 1295 LOG ("Failed to initialize buffer data source\n");
1281 return NULL; 1296 return NULL;
1282 } 1297 }
1283 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource)))) 1298 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource))))
1284 { 1299 {
1285 LOG_STRERROR ("malloc"); 1300 LOG_STRERROR ("malloc");
1286 bfds_delete (bfds); 1301 bfds_delete (bfds);
1287 return NULL; 1302 return NULL;
1288 } 1303 }
1289 ds->bfds = bfds; 1304 ds->bfds = bfds;
1290 ds->fd = -1; 1305 ds->fd = -1;
1291 ds->cfs = NULL; 1306 ds->cfs = NULL;
1292 ct = get_compression_type (bfds); 1307 ct = get_compression_type (bfds);
1293 if ( (COMP_TYPE_ZLIB == ct) || 1308 if ( (COMP_TYPE_ZLIB == ct) ||
1294 (COMP_TYPE_BZ2 == ct) ) 1309 (COMP_TYPE_BZ2 == ct) )
1310 {
1311 ds->cfs = cfs_new (bfds, size, ct, proc, proc_cls);
1312 if (NULL == ds->cfs)
1295 { 1313 {
1296 ds->cfs = cfs_new (bfds, size, ct, proc, proc_cls); 1314 LOG ("Failed to initialize decompressor\n");
1297 if (NULL == ds->cfs) 1315 bfds_delete (bfds);
1298 { 1316 free (ds);
1299 LOG ("Failed to initialize decompressor\n"); 1317 return NULL;
1300 bfds_delete (bfds);
1301 free (ds);
1302 return NULL;
1303 }
1304 } 1318 }
1319 }
1305 return ds; 1320 return ds;
1306} 1321}
1307 1322
@@ -1334,8 +1349,8 @@ EXTRACTOR_datasource_destroy_ (struct EXTRACTOR_Datasource *ds)
1334 */ 1349 */
1335ssize_t 1350ssize_t
1336EXTRACTOR_datasource_read_ (void *cls, 1351EXTRACTOR_datasource_read_ (void *cls,
1337 void *data, 1352 void *data,
1338 size_t size) 1353 size_t size)
1339{ 1354{
1340 struct EXTRACTOR_Datasource *ds = cls; 1355 struct EXTRACTOR_Datasource *ds = cls;
1341 1356
@@ -1357,23 +1372,23 @@ EXTRACTOR_datasource_read_ (void *cls,
1357 */ 1372 */
1358int64_t 1373int64_t
1359EXTRACTOR_datasource_seek_ (void *cls, 1374EXTRACTOR_datasource_seek_ (void *cls,
1360 int64_t pos, 1375 int64_t pos,
1361 int whence) 1376 int whence)
1362{ 1377{
1363 struct EXTRACTOR_Datasource *ds = cls; 1378 struct EXTRACTOR_Datasource *ds = cls;
1364 1379
1365 if (NULL != ds->cfs) 1380 if (NULL != ds->cfs)
1381 {
1382 if ( (SEEK_END == whence) &&
1383 (-1 == ds->cfs->uncompressed_size) )
1366 { 1384 {
1367 if ( (SEEK_END == whence) && 1385 /* need to obtain uncompressed size */
1368 (-1 == ds->cfs->uncompressed_size) ) 1386 (void) EXTRACTOR_datasource_get_size_ (ds, 1);
1369 { 1387 if (-1 == ds->cfs->uncompressed_size)
1370 /* need to obtain uncompressed size */ 1388 return -1;
1371 (void) EXTRACTOR_datasource_get_size_ (ds, 1);
1372 if (-1 == ds->cfs->uncompressed_size)
1373 return -1;
1374 }
1375 return cfs_seek (ds->cfs, pos, whence);
1376 } 1389 }
1390 return cfs_seek (ds->cfs, pos, whence);
1391 }
1377 return bfds_seek (ds->bfds, pos, whence); 1392 return bfds_seek (ds->bfds, pos, whence);
1378} 1393}
1379 1394
@@ -1387,30 +1402,32 @@ EXTRACTOR_datasource_seek_ (void *cls,
1387 */ 1402 */
1388int64_t 1403int64_t
1389EXTRACTOR_datasource_get_size_ (void *cls, 1404EXTRACTOR_datasource_get_size_ (void *cls,
1390 int force) 1405 int force)
1391{ 1406{
1392 struct EXTRACTOR_Datasource *ds = cls; 1407 struct EXTRACTOR_Datasource *ds = cls;
1393 char buf[32 * 1024]; 1408 char buf[32 * 1024];
1394 uint64_t pos; 1409 uint64_t pos;
1395 1410
1396 if (NULL != ds->cfs) 1411 if (NULL != ds->cfs)
1412 {
1413 if ( (force) &&
1414 (-1 == ds->cfs->uncompressed_size) )
1397 { 1415 {
1398 if ( (force) && 1416 pos = ds->cfs->fpos;
1399 (-1 == ds->cfs->uncompressed_size) ) 1417 while ( (-1 == ds->cfs->uncompressed_size) &&
1400 { 1418 (-1 != cfs_read (ds->cfs, buf, sizeof (buf))) )
1401 pos = ds->cfs->fpos; 1419 ;
1402 while ( (-1 == ds->cfs->uncompressed_size) && 1420 if (-1 == cfs_seek (ds->cfs, pos, SEEK_SET))
1403 (-1 != cfs_read (ds->cfs, buf, sizeof (buf))) ) ; 1421 {
1404 if (-1 == cfs_seek (ds->cfs, pos, SEEK_SET)) 1422 LOG (
1405 { 1423 "Serious problem, I moved the buffer to determine the file size but could not restore it...\n");
1406 LOG ("Serious problem, I moved the buffer to determine the file size but could not restore it...\n"); 1424 return -1;
1407 return -1; 1425 }
1408 } 1426 if (-1 == ds->cfs->uncompressed_size)
1409 if (-1 == ds->cfs->uncompressed_size) 1427 return -1;
1410 return -1;
1411 }
1412 return ds->cfs->uncompressed_size;
1413 } 1428 }
1429 return ds->cfs->uncompressed_size;
1430 }
1414 return ds->bfds->fsize; 1431 return ds->bfds->fsize;
1415} 1432}
1416 1433
diff --git a/src/main/extractor_datasource.h b/src/main/extractor_datasource.h
index f25cc4b..dc548a6 100644
--- a/src/main/extractor_datasource.h
+++ b/src/main/extractor_datasource.h
@@ -29,7 +29,7 @@
29 29
30/** 30/**
31 * Handle to a datasource we can use for the plugins. 31 * Handle to a datasource we can use for the plugins.
32 */ 32 */
33struct EXTRACTOR_Datasource; 33struct EXTRACTOR_Datasource;
34 34
35 35
@@ -43,7 +43,8 @@ struct EXTRACTOR_Datasource;
43 */ 43 */
44struct EXTRACTOR_Datasource * 44struct EXTRACTOR_Datasource *
45EXTRACTOR_datasource_create_from_file_ (const char *filename, 45EXTRACTOR_datasource_create_from_file_ (const char *filename,
46 EXTRACTOR_MetaDataProcessor proc, void *proc_cls); 46 EXTRACTOR_MetaDataProcessor proc,
47 void *proc_cls);
47 48
48 49
49/** 50/**
@@ -57,8 +58,9 @@ EXTRACTOR_datasource_create_from_file_ (const char *filename,
57 */ 58 */
58struct EXTRACTOR_Datasource * 59struct EXTRACTOR_Datasource *
59EXTRACTOR_datasource_create_from_buffer_ (const char *buf, 60EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
60 size_t size, 61 size_t size,
61 EXTRACTOR_MetaDataProcessor proc, void *proc_cls); 62 EXTRACTOR_MetaDataProcessor proc,
63 void *proc_cls);
62 64
63 65
64/** 66/**
@@ -81,14 +83,14 @@ EXTRACTOR_datasource_destroy_ (struct EXTRACTOR_Datasource *ds);
81 */ 83 */
82ssize_t 84ssize_t
83EXTRACTOR_datasource_read_ (void *cls, 85EXTRACTOR_datasource_read_ (void *cls,
84 void *data, 86 void *data,
85 size_t size); 87 size_t size);
86 88
87 89
88/** 90/**
89 * Seek in the datasource. Use 'SEEK_CUR' for whence and 'pos' of 0 to 91 * Seek in the datasource. Use 'SEEK_CUR' for whence and 'pos' of 0 to
90 * obtain the current position in the file. 92 * obtain the current position in the file.
91 * 93 *
92 * @param cls must be a 'struct EXTRACTOR_Datasource' 94 * @param cls must be a 'struct EXTRACTOR_Datasource'
93 * @param pos position to seek (see 'man lseek')o 95 * @param pos position to seek (see 'man lseek')o
94 * @param whence how to see (absolute to start, relative, absolute to end) 96 * @param whence how to see (absolute to start, relative, absolute to end)
@@ -97,20 +99,20 @@ EXTRACTOR_datasource_read_ (void *cls,
97 */ 99 */
98int64_t 100int64_t
99EXTRACTOR_datasource_seek_ (void *cls, 101EXTRACTOR_datasource_seek_ (void *cls,
100 int64_t pos, 102 int64_t pos,
101 int whence); 103 int whence);
102 104
103 105
104/** 106/**
105 * Determine the overall size of the data source (after compression). 107 * Determine the overall size of the data source (after compression).
106 * 108 *
107 * @param cls must be a 'struct EXTRACTOR_Datasource' 109 * @param cls must be a 'struct EXTRACTOR_Datasource'
108 * @param force force computing the size if it is unavailable 110 * @param force force computing the size if it is unavailable
109 * @return overall file size, -1 on error or unknown 111 * @return overall file size, -1 on error or unknown
110 */ 112 */
111int64_t 113int64_t
112EXTRACTOR_datasource_get_size_ (void *cls, 114EXTRACTOR_datasource_get_size_ (void *cls,
113 int force); 115 int force);
114 116
115 117
116#endif 118#endif
diff --git a/src/main/extractor_ipc.c b/src/main/extractor_ipc.c
index 47d9d4d..b343bd6 100644
--- a/src/main/extractor_ipc.c
+++ b/src/main/extractor_ipc.c
@@ -40,10 +40,10 @@
40 */ 40 */
41ssize_t 41ssize_t
42EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin, 42EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin,
43 const void *data, 43 const void *data,
44 size_t size, 44 size_t size,
45 EXTRACTOR_ChannelMessageProcessor proc, 45 EXTRACTOR_ChannelMessageProcessor proc,
46 void *proc_cls) 46 void *proc_cls)
47{ 47{
48 const char *cdata; 48 const char *cdata;
49 unsigned char code; 49 unsigned char code;
@@ -55,83 +55,84 @@ EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin,
55 55
56 ret = 0; 56 ret = 0;
57 while (size > 0) 57 while (size > 0)
58 {
59 cdata = data;
60 code = (unsigned char) cdata[0];
61 switch (code)
58 { 62 {
59 cdata = data; 63 case MESSAGE_DONE: /* Done */
60 code = (unsigned char) cdata[0]; 64 plugin->seek_request = -1;
61 switch (code) 65 plugin->round_finished = 1;
62 { 66 ret++;
63 case MESSAGE_DONE: /* Done */ 67 size--;
64 plugin->seek_request = -1; 68 data++;
65 plugin->round_finished = 1; 69 continue;
66 ret++; 70 case MESSAGE_SEEK: /* Seek */
67 size--; 71 if (size < sizeof (struct SeekRequestMessage))
68 data++; 72 {
69 continue; 73 plugin->seek_request = -1;
70 case MESSAGE_SEEK: /* Seek */ 74 return ret;
71 if (size < sizeof (struct SeekRequestMessage)) 75 }
72 { 76 memcpy (&seek, cdata, sizeof (seek));
73 plugin->seek_request = -1; 77 plugin->seek_request = (int64_t) seek.file_offset;
74 return ret; 78 plugin->seek_whence = seek.whence;
75 } 79 ret += sizeof (struct SeekRequestMessage);
76 memcpy (&seek, cdata, sizeof (seek)); 80 data += sizeof (struct SeekRequestMessage);
77 plugin->seek_request = (int64_t) seek.file_offset; 81 size -= sizeof (struct SeekRequestMessage);
78 plugin->seek_whence = seek.whence; 82 continue;
79 ret += sizeof (struct SeekRequestMessage); 83 case MESSAGE_META: /* Meta */
80 data += sizeof (struct SeekRequestMessage); 84 if (size < sizeof (struct MetaMessage))
81 size -= sizeof (struct SeekRequestMessage); 85 {
82 continue; 86 plugin->seek_request = -1;
83 case MESSAGE_META: /* Meta */ 87 return ret;
84 if (size < sizeof (struct MetaMessage)) 88 }
85 { 89 memcpy (&meta, cdata, sizeof (meta));
86 plugin->seek_request = -1; 90 /* check hdr for sanity */
87 return ret; 91 if (meta.value_size > MAX_META_DATA)
88 } 92 {
89 memcpy (&meta, cdata, sizeof (meta)); 93 LOG ("Meta data exceeds size limit\n");
90 /* check hdr for sanity */ 94 return -1; /* not allowing more than MAX_META_DATA meta data */
91 if (meta.value_size > MAX_META_DATA) 95 }
92 { 96 if (size < sizeof (meta) + meta.mime_length + meta.value_size)
93 LOG ("Meta data exceeds size limit\n"); 97 {
94 return -1; /* not allowing more than MAX_META_DATA meta data */ 98 plugin->seek_request = -1;
95 } 99 return ret;
96 if (size < sizeof (meta) + meta.mime_length + meta.value_size) 100 }
97 { 101 if (0 == meta.mime_length)
98 plugin->seek_request = -1; 102 {
99 return ret; 103 mime_type = NULL;
100 } 104 }
101 if (0 == meta.mime_length) 105 else
102 { 106 {
103 mime_type = NULL; 107 mime_type = &cdata[sizeof (struct MetaMessage)];
104 } 108 if ('\0' != mime_type[meta.mime_length - 1])
105 else 109 {
106 { 110 LOG ("Mime type not 0-terminated\n");
107 mime_type = &cdata[sizeof (struct MetaMessage)]; 111 return -1;
108 if ('\0' != mime_type[meta.mime_length - 1]) 112 }
109 { 113 }
110 LOG ("Mime type not 0-terminated\n"); 114 if (0 == meta.value_size)
111 return -1; 115 value = NULL;
112 } 116 else
113 } 117 value = &cdata[sizeof (struct MetaMessage) + meta.mime_length];
114 if (0 == meta.value_size) 118 if (meta.meta_type >= EXTRACTOR_metatype_get_max ())
115 value = NULL; 119 meta.meta_type = EXTRACTOR_METATYPE_UNKNOWN;
116 else 120 proc (proc_cls,
117 value = &cdata[sizeof (struct MetaMessage) + meta.mime_length]; 121 plugin,
118 if (meta.meta_type >= EXTRACTOR_metatype_get_max ()) 122 (enum EXTRACTOR_MetaType) meta.meta_type,
119 meta.meta_type = EXTRACTOR_METATYPE_UNKNOWN; 123 (enum EXTRACTOR_MetaFormat) meta.meta_format,
120 proc (proc_cls, 124 mime_type, value, meta.value_size);
121 plugin, 125 ret += sizeof (struct MetaMessage) + meta.mime_length + meta.value_size;
122 (enum EXTRACTOR_MetaType) meta.meta_type, 126 size -= sizeof (struct MetaMessage) + meta.mime_length + meta.value_size;
123 (enum EXTRACTOR_MetaFormat) meta.meta_format, 127 data += sizeof (struct MetaMessage) + meta.mime_length + meta.value_size;
124 mime_type, value, meta.value_size); 128 continue;
125 ret += sizeof (struct MetaMessage) + meta.mime_length + meta.value_size; 129 default:
126 size -= sizeof (struct MetaMessage) + meta.mime_length + meta.value_size; 130 LOG ("Invalid message type %d\n", (int) code);
127 data += sizeof (struct MetaMessage) + meta.mime_length + meta.value_size; 131 return -1;
128 continue;
129 default:
130 LOG ("Invalid message type %d\n", (int) code);
131 return -1;
132 }
133 } 132 }
133 }
134 return ret; 134 return ret;
135} 135}
136 136
137
137/* end of extractor_ipc.c */ 138/* end of extractor_ipc.c */
diff --git a/src/main/extractor_ipc.h b/src/main/extractor_ipc.h
index 0109b66..8e7fe09 100644
--- a/src/main/extractor_ipc.h
+++ b/src/main/extractor_ipc.h
@@ -27,7 +27,7 @@
27 * as follows. Each message begins with a 1-character opcode which 27 * as follows. Each message begins with a 1-character opcode which
28 * specifies the message type. The main library starts the plugins 28 * specifies the message type. The main library starts the plugins
29 * by forking the helper process and establishes two pipes for 29 * by forking the helper process and establishes two pipes for
30 * communication in both directions. 30 * communication in both directions.
31 * First, the main library send an 'INIT_STATE' message 31 * First, the main library send an 'INIT_STATE' message
32 * to the plugin. The start message specifies the name (and size) 32 * to the plugin. The start message specifies the name (and size)
33 * of a shared memory segment which will contain parts of the (uncompressed) 33 * of a shared memory segment which will contain parts of the (uncompressed)
@@ -39,7 +39,7 @@
39 * size of the file (or -1 if unknown) and the number of bytes 39 * size of the file (or -1 if unknown) and the number of bytes
40 * ready in the shared memory segment. The plugin then answers 40 * ready in the shared memory segment. The plugin then answers
41 * with either: 41 * with either:
42 * 1) MESSAGE_DONE to indicate that no further processing is 42 * 1) MESSAGE_DONE to indicate that no further processing is
43 * required for this file; the IPC continues with the 43 * required for this file; the IPC continues with the
44 * EXTRACT_START message for the next file afterwards; 44 * EXTRACT_START message for the next file afterwards;
45 * 2) MESSAGE_SEEK to indicate that the plugin would like to 45 * 2) MESSAGE_SEEK to indicate that the plugin would like to
@@ -161,7 +161,7 @@ struct StartMessage
161 161
162/** 162/**
163 * Sent from LE to a plugin to tell it that shm contents 163 * Sent from LE to a plugin to tell it that shm contents
164 * were updated. 164 * were updated.
165 */ 165 */
166#define MESSAGE_UPDATED_SHM 0x02 166#define MESSAGE_UPDATED_SHM 0x02
167 167
@@ -245,7 +245,7 @@ struct SeekRequestMessage
245 /** 245 /**
246 * Requested offset; a positive value from the end of the 246 * Requested offset; a positive value from the end of the
247 * file is used of 'whence' is SEEK_END; a postive value 247 * file is used of 'whence' is SEEK_END; a postive value
248 * from the start is used of 'whence' is SEEK_SET. 248 * from the start is used of 'whence' is SEEK_SET.
249 * 'SEEK_CUR' is never used. 249 * 'SEEK_CUR' is never used.
250 */ 250 */
251 uint64_t file_offset; 251 uint64_t file_offset;
@@ -292,9 +292,9 @@ struct MetaMessage
292 */ 292 */
293 uint32_t value_size; 293 uint32_t value_size;
294 294
295 /* followed by mime_length bytes of 0-terminated 295 /* followed by mime_length bytes of 0-terminated
296 mime-type (unless mime_length is 0) */ 296 mime-type (unless mime_length is 0) */
297 297
298 /* followed by value_size bytes of value */ 298 /* followed by value_size bytes of value */
299 299
300}; 300};
@@ -355,7 +355,7 @@ EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm);
355 */ 355 */
356unsigned int 356unsigned int
357EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm, 357EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
358 int delta); 358 int delta);
359 359
360 360
361/** 361/**
@@ -369,9 +369,9 @@ EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
369 */ 369 */
370ssize_t 370ssize_t
371EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm, 371EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
372 struct EXTRACTOR_Datasource *ds, 372 struct EXTRACTOR_Datasource *ds,
373 uint64_t off, 373 uint64_t off,
374 size_t size); 374 size_t size);
375 375
376 376
377/** 377/**
@@ -391,10 +391,10 @@ EXTRACTOR_datasource_get_pos_ (struct EXTRACTOR_Datasource *ds);
391 * @param plugin the plugin 391 * @param plugin the plugin
392 * @param shm memory to share with the process 392 * @param shm memory to share with the process
393 * @return NULL on error, otherwise IPC channel 393 * @return NULL on error, otherwise IPC channel
394 */ 394 */
395struct EXTRACTOR_Channel * 395struct EXTRACTOR_Channel *
396EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin, 396EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
397 struct EXTRACTOR_SharedMemory *shm); 397 struct EXTRACTOR_SharedMemory *shm);
398 398
399 399
400/** 400/**
@@ -418,8 +418,8 @@ EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel);
418 */ 418 */
419ssize_t 419ssize_t
420EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel, 420EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
421 const void *data, 421 const void *data,
422 size_t size); 422 size_t size);
423 423
424 424
425/** 425/**
@@ -434,12 +434,15 @@ EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
434 * @param value_len number of bytes in 'value' 434 * @param value_len number of bytes in 'value'
435 */ 435 */
436typedef void (*EXTRACTOR_ChannelMessageProcessor) (void *cls, 436typedef void (*EXTRACTOR_ChannelMessageProcessor) (void *cls,
437 struct EXTRACTOR_PluginList *plugin, 437 struct EXTRACTOR_PluginList *
438 enum EXTRACTOR_MetaType meta_type, 438 plugin,
439 enum EXTRACTOR_MetaFormat meta_format, 439 enum EXTRACTOR_MetaType
440 const char *mime, 440 meta_type,
441 const void *value, 441 enum EXTRACTOR_MetaFormat
442 size_t value_len); 442 meta_format,
443 const char *mime,
444 const void *value,
445 size_t value_len);
443 446
444 447
445/** 448/**
@@ -454,10 +457,10 @@ typedef void (*EXTRACTOR_ChannelMessageProcessor) (void *cls,
454 */ 457 */
455ssize_t 458ssize_t
456EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin, 459EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin,
457 const void *data, 460 const void *data,
458 size_t size, 461 size_t size,
459 EXTRACTOR_ChannelMessageProcessor proc, 462 EXTRACTOR_ChannelMessageProcessor proc,
460 void *proc_cls); 463 void *proc_cls);
461 464
462 465
463/** 466/**
@@ -473,9 +476,9 @@ EXTRACTOR_IPC_process_reply_ (struct EXTRACTOR_PluginList *plugin,
473 */ 476 */
474int 477int
475EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels, 478EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
476 unsigned int num_channels, 479 unsigned int num_channels,
477 EXTRACTOR_ChannelMessageProcessor proc, 480 EXTRACTOR_ChannelMessageProcessor proc,
478 void *proc_cls); 481 void *proc_cls);
479 482
480 483
481#endif 484#endif
diff --git a/src/main/extractor_ipc_gnu.c b/src/main/extractor_ipc_gnu.c
index 7bb8914..5400636 100644
--- a/src/main/extractor_ipc_gnu.c
+++ b/src/main/extractor_ipc_gnu.c
@@ -138,10 +138,10 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
138 const char *tpath; 138 const char *tpath;
139 139
140 if (NULL == (shm = malloc (sizeof (struct EXTRACTOR_SharedMemory)))) 140 if (NULL == (shm = malloc (sizeof (struct EXTRACTOR_SharedMemory))))
141 { 141 {
142 LOG_STRERROR ("malloc"); 142 LOG_STRERROR ("malloc");
143 return NULL; 143 return NULL;
144 } 144 }
145#if SOMEBSD 145#if SOMEBSD
146 /* this works on FreeBSD, not sure about others... */ 146 /* this works on FreeBSD, not sure about others... */
147 tpath = getenv ("TMPDIR"); 147 tpath = getenv ("TMPDIR");
@@ -151,24 +151,24 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
151 tpath = "/"; /* Linux */ 151 tpath = "/"; /* Linux */
152#endif 152#endif
153 snprintf (shm->shm_name, 153 snprintf (shm->shm_name,
154 MAX_SHM_NAME, 154 MAX_SHM_NAME,
155 "%sLE-%u-%u", 155 "%sLE-%u-%u",
156 tpath, getpid (), 156 tpath, getpid (),
157 (unsigned int) RANDOM()); 157 (unsigned int) RANDOM ());
158 if (-1 == (shm->shm_id = shm_open (shm->shm_name, 158 if (-1 == (shm->shm_id = shm_open (shm->shm_name,
159 O_RDWR | O_CREAT, S_IRUSR | S_IWUSR))) 159 O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)))
160 { 160 {
161 LOG_STRERROR_FILE ("shm_open", 161 LOG_STRERROR_FILE ("shm_open",
162 shm->shm_name); 162 shm->shm_name);
163 free (shm); 163 free (shm);
164 return NULL; 164 return NULL;
165 } 165 }
166 if ( (0 != ftruncate (shm->shm_id, size)) || 166 if ( (0 != ftruncate (shm->shm_id, size)) ||
167 (NULL == (shm->shm_ptr = mmap (NULL, 167 (NULL == (shm->shm_ptr = mmap (NULL,
168 size, 168 size,
169 PROT_WRITE, 169 PROT_WRITE,
170 MAP_SHARED, 170 MAP_SHARED,
171 shm->shm_id, 171 shm->shm_id,
172 0))) || 172 0))) ||
173 (((void*) -1) == shm->shm_ptr) ) 173 (((void*) -1) == shm->shm_ptr) )
174 { 174 {
@@ -193,7 +193,7 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
193 */ 193 */
194unsigned int 194unsigned int
195EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm, 195EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
196 int delta) 196 int delta)
197{ 197{
198 shm->rc += delta; 198 shm->rc += delta;
199 return shm->rc; 199 return shm->rc;
@@ -228,23 +228,23 @@ EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm)
228 */ 228 */
229ssize_t 229ssize_t
230EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm, 230EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
231 struct EXTRACTOR_Datasource *ds, 231 struct EXTRACTOR_Datasource *ds,
232 uint64_t off, 232 uint64_t off,
233 size_t size) 233 size_t size)
234{ 234{
235 if (-1 == 235 if (-1 ==
236 EXTRACTOR_datasource_seek_ (ds, 236 EXTRACTOR_datasource_seek_ (ds,
237 off, 237 off,
238 SEEK_SET)) 238 SEEK_SET))
239 { 239 {
240 LOG ("Failed to set IPC memory due to seek error\n"); 240 LOG ("Failed to set IPC memory due to seek error\n");
241 return -1; 241 return -1;
242 } 242 }
243 if (size > shm->shm_size) 243 if (size > shm->shm_size)
244 size = shm->shm_size; 244 size = shm->shm_size;
245 return EXTRACTOR_datasource_read_ (ds, 245 return EXTRACTOR_datasource_read_ (ds,
246 shm->shm_ptr, 246 shm->shm_ptr,
247 size); 247 size);
248} 248}
249 249
250 250
@@ -277,7 +277,7 @@ EXTRACTOR_datasource_get_pos_ (struct EXTRACTOR_Datasource *ds)
277 */ 277 */
278struct EXTRACTOR_Channel * 278struct EXTRACTOR_Channel *
279EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin, 279EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
280 struct EXTRACTOR_SharedMemory *shm) 280 struct EXTRACTOR_SharedMemory *shm)
281{ 281{
282 struct EXTRACTOR_Channel *channel; 282 struct EXTRACTOR_Channel *channel;
283 int p1[2]; 283 int p1[2];
@@ -287,74 +287,74 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
287 size_t slen; 287 size_t slen;
288 288
289 if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel)))) 289 if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel))))
290 { 290 {
291 LOG_STRERROR ("malloc"); 291 LOG_STRERROR ("malloc");
292 return NULL; 292 return NULL;
293 } 293 }
294 channel->mdata_size = 1024; 294 channel->mdata_size = 1024;
295 if (NULL == (channel->mdata = malloc (channel->mdata_size))) 295 if (NULL == (channel->mdata = malloc (channel->mdata_size)))
296 { 296 {
297 LOG_STRERROR ("malloc"); 297 LOG_STRERROR ("malloc");
298 free (channel); 298 free (channel);
299 return NULL; 299 return NULL;
300 } 300 }
301 channel->shm = shm; 301 channel->shm = shm;
302 channel->plugin = plugin; 302 channel->plugin = plugin;
303 channel->size = 0; 303 channel->size = 0;
304 if (0 != pipe (p1)) 304 if (0 != pipe (p1))
305 { 305 {
306 LOG_STRERROR ("pipe"); 306 LOG_STRERROR ("pipe");
307 free (channel->mdata); 307 free (channel->mdata);
308 free (channel); 308 free (channel);
309 return NULL; 309 return NULL;
310 } 310 }
311 if (0 != pipe (p2)) 311 if (0 != pipe (p2))
312 { 312 {
313 LOG_STRERROR ("pipe"); 313 LOG_STRERROR ("pipe");
314 (void) close (p1[0]); 314 (void) close (p1[0]);
315 (void) close (p1[1]); 315 (void) close (p1[1]);
316 free (channel->mdata); 316 free (channel->mdata);
317 free (channel); 317 free (channel);
318 return NULL; 318 return NULL;
319 } 319 }
320 pid = fork (); 320 pid = fork ();
321 if (pid == -1) 321 if (pid == -1)
322 { 322 {
323 LOG_STRERROR ("fork"); 323 LOG_STRERROR ("fork");
324 (void) close (p1[0]); 324 (void) close (p1[0]);
325 (void) close (p1[1]); 325 (void) close (p1[1]);
326 (void) close (p2[0]); 326 (void) close (p2[0]);
327 (void) close (p2[1]); 327 (void) close (p2[1]);
328 free (channel->mdata); 328 free (channel->mdata);
329 free (channel); 329 free (channel);
330 return NULL; 330 return NULL;
331 } 331 }
332 if (0 == pid) 332 if (0 == pid)
333 { 333 {
334 (void) close (p1[1]); 334 (void) close (p1[1]);
335 (void) close (p2[0]); 335 (void) close (p2[0]);
336 free (channel->mdata); 336 free (channel->mdata);
337 free (channel); 337 free (channel);
338#if HAVE_SYS_APPARMOR_H 338#if HAVE_SYS_APPARMOR_H
339#if HAVE_APPARMOR 339#if HAVE_APPARMOR
340 if (0 > aa_change_profile("libextractor")) 340 if (0 > aa_change_profile ("libextractor"))
341 {
342 int eno = errno;
343
344 if ( (EINVAL != eno) &&
345 (ENOENT != eno) )
341 { 346 {
342 int eno = errno; 347 fprintf (stderr,
343 348 "Failure changing AppArmor profile: %s\n",
344 if ( (EINVAL != eno) && 349 strerror (errno));
345 (ENOENT != eno) ) 350 _exit (1);
346 {
347 fprintf (stderr,
348 "Failure changing AppArmor profile: %s\n",
349 strerror (errno));
350 _exit(1);
351 }
352 } 351 }
352 }
353#endif 353#endif
354#endif 354#endif
355 EXTRACTOR_plugin_main_ (plugin, p1[0], p2[1]); 355 EXTRACTOR_plugin_main_ (plugin, p1[0], p2[1]);
356 _exit (0); 356 _exit (0);
357 } 357 }
358 (void) close (p1[0]); 358 (void) close (p1[0]);
359 (void) close (p2[1]); 359 (void) close (p2[1]);
360 channel->cpipe_in = p1[1]; 360 channel->cpipe_in = p1[1];
@@ -362,11 +362,11 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
362 channel->cpid = pid; 362 channel->cpid = pid;
363 slen = strlen (shm->shm_name) + 1; 363 slen = strlen (shm->shm_name) + 1;
364 if (NULL == (init = malloc (sizeof (struct InitMessage) + slen))) 364 if (NULL == (init = malloc (sizeof (struct InitMessage) + slen)))
365 { 365 {
366 LOG_STRERROR ("malloc"); 366 LOG_STRERROR ("malloc");
367 EXTRACTOR_IPC_channel_destroy_ (channel); 367 EXTRACTOR_IPC_channel_destroy_ (channel);
368 return NULL; 368 return NULL;
369 } 369 }
370 init->opcode = MESSAGE_INIT_STATE; 370 init->opcode = MESSAGE_INIT_STATE;
371 init->reserved = 0; 371 init->reserved = 0;
372 init->reserved2 = 0; 372 init->reserved2 = 0;
@@ -375,14 +375,14 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
375 memcpy (&init[1], shm->shm_name, slen); 375 memcpy (&init[1], shm->shm_name, slen);
376 if (sizeof (struct InitMessage) + slen != 376 if (sizeof (struct InitMessage) + slen !=
377 EXTRACTOR_IPC_channel_send_ (channel, 377 EXTRACTOR_IPC_channel_send_ (channel,
378 init, 378 init,
379 sizeof (struct InitMessage) + slen) ) 379 sizeof (struct InitMessage) + slen) )
380 { 380 {
381 LOG ("Failed to send INIT_STATE message to plugin\n"); 381 LOG ("Failed to send INIT_STATE message to plugin\n");
382 EXTRACTOR_IPC_channel_destroy_ (channel); 382 EXTRACTOR_IPC_channel_destroy_ (channel);
383 free (init); 383 free (init);
384 return NULL; 384 return NULL;
385 } 385 }
386 free (init); 386 free (init);
387 return channel; 387 return channel;
388} 388}
@@ -425,24 +425,24 @@ EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel)
425 */ 425 */
426ssize_t 426ssize_t
427EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel, 427EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
428 const void *data, 428 const void *data,
429 size_t size) 429 size_t size)
430{ 430{
431 const char *cdata = data; 431 const char *cdata = data;
432 size_t off = 0; 432 size_t off = 0;
433 ssize_t ret; 433 ssize_t ret;
434 434
435 while (off < size) 435 while (off < size)
436 {
437 ret = write (channel->cpipe_in, &cdata[off], size - off);
438 if (ret <= 0)
436 { 439 {
437 ret = write (channel->cpipe_in, &cdata[off], size - off); 440 if (-1 == ret)
438 if (ret <= 0) 441 LOG_STRERROR ("write");
439 { 442 return -1;
440 if (-1 == ret)
441 LOG_STRERROR ("write");
442 return -1;
443 }
444 off += ret;
445 } 443 }
444 off += ret;
445 }
446 return size; 446 return size;
447} 447}
448 448
@@ -464,9 +464,9 @@ EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
464 */ 464 */
465int 465int
466EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels, 466EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
467 unsigned int num_channels, 467 unsigned int num_channels,
468 EXTRACTOR_ChannelMessageProcessor proc, 468 EXTRACTOR_ChannelMessageProcessor proc,
469 void *proc_cls) 469 void *proc_cls)
470{ 470{
471 struct timeval tv; 471 struct timeval tv;
472 fd_set to_check; 472 fd_set to_check;
@@ -480,105 +480,106 @@ EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
480 480
481 FD_ZERO (&to_check); 481 FD_ZERO (&to_check);
482 max = -1; 482 max = -1;
483 for (i=0;i<num_channels;i++) 483 for (i = 0; i<num_channels; i++)
484 {
485 channel = channels[i];
486 if (NULL == channel)
487 continue;
488 FD_SET (channel->cpipe_out, &to_check);
489 if (max < channel->cpipe_out)
490 max = channel->cpipe_out;
491 }
492 if (-1 == max)
493 {
494 return 1; /* nothing left to do! */
495 }
496 tv.tv_sec = 0;
497 tv.tv_usec = 500000; /* 500 ms */
498 if (0 >= select (max + 1, &to_check, NULL, NULL, &tv))
499 {
500 /* an error or timeout -> something's wrong or all plugins hung up */
501 closed_channel = 0;
502 for (i = 0; i<num_channels; i++)
484 { 503 {
485 channel = channels[i]; 504 channel = channels[i];
486 if (NULL == channel) 505 if (NULL == channel)
487 continue; 506 continue;
488 FD_SET (channel->cpipe_out, &to_check); 507 if (-1 == channel->plugin->seek_request)
489 if (max < channel->cpipe_out) 508 {
490 max = channel->cpipe_out; 509 /* plugin blocked for too long, kill channel */
510 LOG ("Channel blocked, closing channel to %s\n",
511 channel->plugin->libname);
512 channel->plugin->channel = NULL;
513 channel->plugin->round_finished = 1;
514 EXTRACTOR_IPC_channel_destroy_ (channel);
515 channels[i] = NULL;
516 closed_channel = 1;
517 }
491 } 518 }
492 if (-1 == max) 519 if (1 == closed_channel)
520 return 1;
521 /* strange, no channel is to blame, let's die just to be safe */
522 if ((EINTR != errno) && (0 != errno))
523 LOG_STRERROR ("select");
524 return -1;
525 }
526 for (i = 0; i<num_channels; i++)
527 {
528 channel = channels[i];
529 if (NULL == channel)
530 continue;
531 if (! FD_ISSET (channel->cpipe_out, &to_check))
532 continue;
533 if (channel->mdata_size == channel->size)
493 { 534 {
494 return 1; /* nothing left to do! */ 535 /* not enough space, need to grow allocation (if allowed) */
536 if (MAX_META_DATA == channel->mdata_size)
537 {
538 LOG ("Inbound message from channel too large, aborting\n");
539 EXTRACTOR_IPC_channel_destroy_ (channel);
540 channels[i] = NULL;
541 continue;
542 }
543 channel->mdata_size *= 2;
544 if (channel->mdata_size > MAX_META_DATA)
545 channel->mdata_size = MAX_META_DATA;
546 if (NULL == (ndata = realloc (channel->mdata,
547 channel->mdata_size)))
548 {
549 LOG_STRERROR ("realloc");
550 EXTRACTOR_IPC_channel_destroy_ (channel);
551 channels[i] = NULL;
552 continue;
553 }
554 channel->mdata = ndata;
495 } 555 }
496 tv.tv_sec = 0; 556 if ( (-1 == (iret = read (channel->cpipe_out,
497 tv.tv_usec = 500000; /* 500 ms */ 557 &channel->mdata[channel->size],
498 if (0 >= select (max + 1, &to_check, NULL, NULL, &tv)) 558 channel->mdata_size - channel->size)) ) ||
559 (0 == iret) ||
560 (-1 == (ret = EXTRACTOR_IPC_process_reply_ (channel->plugin,
561 channel->mdata,
562 channel->size + iret,
563 proc, proc_cls)) ) )
499 { 564 {
500 /* an error or timeout -> something's wrong or all plugins hung up */ 565 if (-1 == iret)
501 closed_channel = 0; 566 LOG_STRERROR ("read");
502 for (i=0;i<num_channels;i++) 567 LOG ("Read error from channel, closing channel %s\n",
503 { 568 channel->plugin->libname);
504 channel = channels[i]; 569 EXTRACTOR_IPC_channel_destroy_ (channel);
505 if (NULL == channel) 570 channels[i] = NULL;
506 continue; 571 continue;
507 if (-1 == channel->plugin->seek_request)
508 {
509 /* plugin blocked for too long, kill channel */
510 LOG ("Channel blocked, closing channel to %s\n",
511 channel->plugin->libname);
512 channel->plugin->channel = NULL;
513 channel->plugin->round_finished = 1;
514 EXTRACTOR_IPC_channel_destroy_ (channel);
515 channels[i] = NULL;
516 closed_channel = 1;
517 }
518 }
519 if (1 == closed_channel)
520 return 1;
521 /* strange, no channel is to blame, let's die just to be safe */
522 if ((EINTR != errno) && (0 != errno))
523 LOG_STRERROR ("select");
524 return -1;
525 } 572 }
526 for (i=0;i<num_channels;i++) 573 else
527 { 574 {
528 channel = channels[i]; 575 channel->size = channel->size + iret - ret;
529 if (NULL == channel) 576 memmove (channel->mdata,
530 continue; 577 &channel->mdata[ret],
531 if (! FD_ISSET (channel->cpipe_out, &to_check)) 578 channel->size);
532 continue;
533 if (channel->mdata_size == channel->size)
534 {
535 /* not enough space, need to grow allocation (if allowed) */
536 if (MAX_META_DATA == channel->mdata_size)
537 {
538 LOG ("Inbound message from channel too large, aborting\n");
539 EXTRACTOR_IPC_channel_destroy_ (channel);
540 channels[i] = NULL;
541 continue;
542 }
543 channel->mdata_size *= 2;
544 if (channel->mdata_size > MAX_META_DATA)
545 channel->mdata_size = MAX_META_DATA;
546 if (NULL == (ndata = realloc (channel->mdata,
547 channel->mdata_size)))
548 {
549 LOG_STRERROR ("realloc");
550 EXTRACTOR_IPC_channel_destroy_ (channel);
551 channels[i] = NULL;
552 continue;
553 }
554 channel->mdata = ndata;
555 }
556 if ( (-1 == (iret = read (channel->cpipe_out,
557 &channel->mdata[channel->size],
558 channel->mdata_size - channel->size)) ) ||
559 (0 == iret) ||
560 (-1 == (ret = EXTRACTOR_IPC_process_reply_ (channel->plugin,
561 channel->mdata,
562 channel->size + iret,
563 proc, proc_cls)) ) )
564 {
565 if (-1 == iret)
566 LOG_STRERROR ("read");
567 LOG ("Read error from channel, closing channel %s\n",
568 channel->plugin->libname);
569 EXTRACTOR_IPC_channel_destroy_ (channel);
570 channels[i] = NULL;
571 continue;
572 }
573 else
574 {
575 channel->size = channel->size + iret - ret;
576 memmove (channel->mdata,
577 &channel->mdata[ret],
578 channel->size);
579 }
580 } 579 }
580 }
581 return 1; 581 return 1;
582} 582}
583 583
584
584/* end of extractor_ipc_gnu.c */ 585/* end of extractor_ipc_gnu.c */
diff --git a/src/main/extractor_ipc_w32.c b/src/main/extractor_ipc_w32.c
index c4fbf1b..b53bc3c 100644
--- a/src/main/extractor_ipc_w32.c
+++ b/src/main/extractor_ipc_w32.c
@@ -34,32 +34,32 @@ struct EXTRACTOR_SharedMemory
34 34
35 /** 35 /**
36 * W32 handle of the shm into which data is uncompressed 36 * W32 handle of the shm into which data is uncompressed
37 */ 37 */
38 HANDLE map; 38 HANDLE map;
39 39
40 /** 40 /**
41 * Name of the shm 41 * Name of the shm
42 */ 42 */
43 char shm_name[MAX_SHM_NAME + 1]; 43 char shm_name[MAX_SHM_NAME + 1];
44 44
45 /** 45 /**
46 * Pointer to the mapped region of the shm (covers the whole shm) 46 * Pointer to the mapped region of the shm (covers the whole shm)
47 */ 47 */
48 void *ptr; 48 void *ptr;
49 49
50 /** 50 /**
51 * Position within shm 51 * Position within shm
52 */ 52 */
53 int64_t pos; 53 int64_t pos;
54 54
55 /** 55 /**
56 * Allocated size of the shm 56 * Allocated size of the shm
57 */ 57 */
58 int64_t shm_size; 58 int64_t shm_size;
59 59
60 /** 60 /**
61 * Number of bytes in shm (<= shm_size) 61 * Number of bytes in shm (<= shm_size)
62 */ 62 */
63 size_t shm_buf_size; 63 size_t shm_buf_size;
64 64
65 size_t shm_map_size; 65 size_t shm_map_size;
@@ -132,11 +132,11 @@ struct EXTRACTOR_Channel
132 */ 132 */
133 char *mdata; 133 char *mdata;
134 134
135 /** 135 /**
136 * Size of the 'mdata' buffer. 136 * Size of the 'mdata' buffer.
137 */ 137 */
138 size_t mdata_size; 138 size_t mdata_size;
139 139
140 /** 140 /**
141 * Number of valid bytes in the channel's buffer. 141 * Number of valid bytes in the channel's buffer.
142 */ 142 */
@@ -159,11 +159,12 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
159 if (NULL == (shm = malloc (sizeof (struct EXTRACTOR_SharedMemory)))) 159 if (NULL == (shm = malloc (sizeof (struct EXTRACTOR_SharedMemory))))
160 return NULL; 160 return NULL;
161 161
162 snprintf (shm->shm_name, MAX_SHM_NAME, 162 snprintf (shm->shm_name, MAX_SHM_NAME,
163 "%slibextractor-shm-%u-%u", 163 "%slibextractor-shm-%u-%u",
164 tpath, getpid(), 164 tpath, getpid (),
165 (unsigned int) RANDOM()); 165 (unsigned int) RANDOM ());
166 shm->map = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm->shm_name); 166 shm->map = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
167 size, shm->shm_name);
167 shm->ptr = MapViewOfFile (shm->map, FILE_MAP_WRITE, 0, 0, size); 168 shm->ptr = MapViewOfFile (shm->map, FILE_MAP_WRITE, 0, 0, size);
168 if (shm->ptr == NULL) 169 if (shm->ptr == NULL)
169 { 170 {
@@ -176,6 +177,7 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
176 return shm; 177 return shm;
177} 178}
178 179
180
179/** 181/**
180 * Change the reference counter for this shm instance. 182 * Change the reference counter for this shm instance.
181 * 183 *
@@ -185,7 +187,7 @@ EXTRACTOR_IPC_shared_memory_create_ (size_t size)
185 */ 187 */
186unsigned int 188unsigned int
187EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm, 189EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
188 int delta) 190 int delta)
189{ 191{
190 shm->rc += delta; 192 shm->rc += delta;
191 return shm->rc; 193 return shm->rc;
@@ -200,7 +202,7 @@ EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm,
200 */ 202 */
201void 203void
202EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm) 204EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm)
203{ 205{
204 if (shm->ptr != NULL) 206 if (shm->ptr != NULL)
205 UnmapViewOfFile (shm->ptr); 207 UnmapViewOfFile (shm->ptr);
206 if (shm->map != 0) 208 if (shm->map != 0)
@@ -208,6 +210,7 @@ EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm)
208 free (shm); 210 free (shm);
209} 211}
210 212
213
211/** 214/**
212 * Initialize shared memory area from data source. 215 * Initialize shared memory area from data source.
213 * 216 *
@@ -219,21 +222,21 @@ EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm)
219 */ 222 */
220ssize_t 223ssize_t
221EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm, 224EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
222 struct EXTRACTOR_Datasource *ds, 225 struct EXTRACTOR_Datasource *ds,
223 uint64_t off, 226 uint64_t off,
224 size_t size) 227 size_t size)
225{ 228{
226 if (-1 == 229 if (-1 ==
227 EXTRACTOR_datasource_seek_ (ds, off, SEEK_SET)) 230 EXTRACTOR_datasource_seek_ (ds, off, SEEK_SET))
228 { 231 {
229 LOG ("Failed to set IPC memory due to seek error\n"); 232 LOG ("Failed to set IPC memory due to seek error\n");
230 return -1; 233 return -1;
231 } 234 }
232 if (size > shm->shm_size) 235 if (size > shm->shm_size)
233 size = shm->shm_size; 236 size = shm->shm_size;
234 return EXTRACTOR_datasource_read_ (ds, 237 return EXTRACTOR_datasource_read_ (ds,
235 shm->ptr, 238 shm->ptr,
236 size); 239 size);
237} 240}
238 241
239 242
@@ -291,7 +294,7 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
291 static volatile LONG pipe_unique_id; 294 static volatile LONG pipe_unique_id;
292 295
293 snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld", 296 snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld",
294 getpid (), InterlockedIncrement ((LONG *) & pipe_unique_id)); 297 getpid (), InterlockedIncrement ((LONG *) &pipe_unique_id));
295 /* Use CreateNamedPipe instead of CreatePipe, because the latter 298 /* Use CreateNamedPipe instead of CreatePipe, because the latter
296 * returns a write handle that does not permit FILE_READ_ATTRIBUTES 299 * returns a write handle that does not permit FILE_READ_ATTRIBUTES
297 * access, on versions of win32 earlier than WinXP SP2. 300 * access, on versions of win32 earlier than WinXP SP2.
@@ -300,8 +303,8 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
300 * It's important to only allow a single instance, to ensure that 303 * It's important to only allow a single instance, to ensure that
301 * the pipe was not created earlier by some other process, even if 304 * the pipe was not created earlier by some other process, even if
302 * the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE 305 * the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
303 * because that is only available for Win2k SP2 and WinXP. */ 306 * because that is only available for Win2k SP2 and WinXP. */read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | dwReadMode,
304 read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | dwReadMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, /* max instances */ 307 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, /* max instances */
305 psize, /* output buffer size */ 308 psize, /* output buffer size */
306 psize, /* input buffer size */ 309 psize, /* input buffer size */
307 NMPWAIT_USE_DEFAULT_WAIT, sa_ptr); 310 NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
@@ -359,6 +362,7 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
359 return 0; 362 return 0;
360} 363}
361 364
365
362/** 366/**
363 * Communicates plugin data (library name, options) to the plugin 367 * Communicates plugin data (library name, options) to the plugin
364 * process. This is only necessary on W32, where this information 368 * process. This is only necessary on W32, where this information
@@ -367,10 +371,10 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
367 * @param plugin plugin context 371 * @param plugin plugin context
368 * 372 *
369 * @return 0 on success, -1 on failure 373 * @return 0 on success, -1 on failure
370 */ 374 */
371static int 375static int
372write_plugin_data (struct EXTRACTOR_PluginList *plugin, 376write_plugin_data (struct EXTRACTOR_PluginList *plugin,
373 struct EXTRACTOR_Channel *channel) 377 struct EXTRACTOR_Channel *channel)
374{ 378{
375 size_t libname_len, shortname_len, opts_len; 379 size_t libname_len, shortname_len, opts_len;
376 DWORD len; 380 DWORD len;
@@ -418,6 +422,7 @@ write_plugin_data (struct EXTRACTOR_PluginList *plugin,
418 return total_len == write_result; 422 return total_len == write_result;
419} 423}
420 424
425
421/** 426/**
422 * Create a channel to communicate with a process wrapping 427 * Create a channel to communicate with a process wrapping
423 * the plugin of the given name. Starts the process as well. 428 * the plugin of the given name. Starts the process as well.
@@ -425,10 +430,10 @@ write_plugin_data (struct EXTRACTOR_PluginList *plugin,
425 * @param plugin the plugin 430 * @param plugin the plugin
426 * @param shm memory to share with the process 431 * @param shm memory to share with the process
427 * @return NULL on error, otherwise IPC channel 432 * @return NULL on error, otherwise IPC channel
428 */ 433 */
429struct EXTRACTOR_Channel * 434struct EXTRACTOR_Channel *
430EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin, 435EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
431 struct EXTRACTOR_SharedMemory *shm) 436 struct EXTRACTOR_SharedMemory *shm)
432{ 437{
433 struct EXTRACTOR_Channel *channel; 438 struct EXTRACTOR_Channel *channel;
434 HANDLE p1[2]; 439 HANDLE p1[2];
@@ -445,18 +450,19 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
445 SECURITY_ATTRIBUTES sa; 450 SECURITY_ATTRIBUTES sa;
446 451
447 if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel)))) 452 if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel))))
448 { 453 {
449 LOG_STRERROR ("malloc"); 454 LOG_STRERROR ("malloc");
450 return NULL; 455 return NULL;
451 } 456 }
452 memset (channel, 0, sizeof (struct EXTRACTOR_Channel)); 457 memset (channel, 0, sizeof (struct EXTRACTOR_Channel));
453 channel->mdata_size = 1024; 458 channel->mdata_size = 1024;
454 if (NULL == (channel->mdata = malloc (channel->mdata_size))) 459 if (NULL == (channel->mdata = malloc (channel->mdata_size)))
455 { 460 {
456 LOG_STRERROR ("malloc"); 461 LOG_STRERROR ("malloc");
457 free (channel); 462 free (channel);
458 return NULL; 463 return NULL;
459 } channel->shm = shm; 464 }
465 channel->shm = shm;
460 channel->plugin = plugin; 466 channel->plugin = plugin;
461 channel->size = 0; 467 channel->size = 0;
462 468
@@ -464,13 +470,15 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
464 sa.lpSecurityDescriptor = NULL; 470 sa.lpSecurityDescriptor = NULL;
465 sa.bInheritHandle = FALSE; 471 sa.bInheritHandle = FALSE;
466 472
467 if (0 != create_selectable_pipe (&p1[0], &p1[1], &sa, 1024, FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED)) 473 if (0 != create_selectable_pipe (&p1[0], &p1[1], &sa, 1024,
474 FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
468 { 475 {
469 LOG_STRERROR ("pipe"); 476 LOG_STRERROR ("pipe");
470 free (channel); 477 free (channel);
471 return NULL; 478 return NULL;
472 } 479 }
473 if (0 != create_selectable_pipe (&p2[0], &p2[1], &sa, 1024, FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED)) 480 if (0 != create_selectable_pipe (&p2[0], &p2[1], &sa, 1024,
481 FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
474 { 482 {
475 LOG_STRERROR ("pipe"); 483 LOG_STRERROR ("pipe");
476 CloseHandle (p1[0]); 484 CloseHandle (p1[0]);
@@ -479,10 +487,10 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
479 return NULL; 487 return NULL;
480 } 488 }
481 489
482 if (!DuplicateHandle (GetCurrentProcess (), p1[0], GetCurrentProcess (), 490 if (! DuplicateHandle (GetCurrentProcess (), p1[0], GetCurrentProcess (),
483 &p10_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS) 491 &p10_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS)
484 || !DuplicateHandle (GetCurrentProcess (), p2[1], GetCurrentProcess (), 492 || ! DuplicateHandle (GetCurrentProcess (), p2[1], GetCurrentProcess (),
485 &p21_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS)) 493 &p21_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS))
486 { 494 {
487 LOG_STRERROR ("DuplicateHandle"); 495 LOG_STRERROR ("DuplicateHandle");
488 if (p10_os_inh != INVALID_HANDLE_VALUE) 496 if (p10_os_inh != INVALID_HANDLE_VALUE)
@@ -506,13 +514,13 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
506 * Also, users might freak out seeing over 9000 rundll32 processes (seeing over 9000 processes named 514 * Also, users might freak out seeing over 9000 rundll32 processes (seeing over 9000 processes named
507 * "libextractor_plugin_helper" is probably less confusing). 515 * "libextractor_plugin_helper" is probably less confusing).
508 */ 516 */
509 snprintf(cmd, MAX_PATH, 517 snprintf (cmd, MAX_PATH,
510 "rundll32.exe libextractor-3.dll,RundllEntryPoint@16 %lu %lu", 518 "rundll32.exe libextractor-3.dll,RundllEntryPoint@16 %lu %lu",
511 p10_os_inh, p21_os_inh); 519 p10_os_inh, p21_os_inh);
512 cmd[MAX_PATH] = '\0'; 520 cmd[MAX_PATH] = '\0';
513 startup.cb = sizeof (STARTUPINFOA); 521 startup.cb = sizeof (STARTUPINFOA);
514 if (CreateProcessA (NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, 522 if (CreateProcessA (NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL,
515 &startup, &proc)) 523 &startup, &proc))
516 { 524 {
517 channel->hProcess = proc.hProcess; 525 channel->hProcess = proc.hProcess;
518 ResumeThread (proc.hThread); 526 ResumeThread (proc.hThread);
@@ -544,7 +552,7 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
544 channel->ov_write.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL); 552 channel->ov_write.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
545 channel->ov_read.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL); 553 channel->ov_read.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
546 554
547 if (!write_plugin_data (plugin, channel)) 555 if (! write_plugin_data (plugin, channel))
548 { 556 {
549 LOG_STRERROR ("write_plugin_data"); 557 LOG_STRERROR ("write_plugin_data");
550 EXTRACTOR_IPC_channel_destroy_ (channel); 558 EXTRACTOR_IPC_channel_destroy_ (channel);
@@ -553,11 +561,11 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
553 561
554 slen = strlen (shm->shm_name) + 1; 562 slen = strlen (shm->shm_name) + 1;
555 if (NULL == (init = malloc (sizeof (struct InitMessage) + slen))) 563 if (NULL == (init = malloc (sizeof (struct InitMessage) + slen)))
556 { 564 {
557 LOG_STRERROR ("malloc"); 565 LOG_STRERROR ("malloc");
558 EXTRACTOR_IPC_channel_destroy_ (channel); 566 EXTRACTOR_IPC_channel_destroy_ (channel);
559 return NULL; 567 return NULL;
560 } 568 }
561 init->opcode = MESSAGE_INIT_STATE; 569 init->opcode = MESSAGE_INIT_STATE;
562 init->reserved = 0; 570 init->reserved = 0;
563 init->reserved2 = 0; 571 init->reserved2 = 0;
@@ -566,17 +574,18 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin,
566 memcpy (&init[1], shm->shm_name, slen); 574 memcpy (&init[1], shm->shm_name, slen);
567 if (sizeof (struct InitMessage) + slen != 575 if (sizeof (struct InitMessage) + slen !=
568 EXTRACTOR_IPC_channel_send_ (channel, init, 576 EXTRACTOR_IPC_channel_send_ (channel, init,
569 sizeof (struct InitMessage) + slen)) 577 sizeof (struct InitMessage) + slen))
570 { 578 {
571 LOG ("Failed to send INIT_STATE message to plugin\n"); 579 LOG ("Failed to send INIT_STATE message to plugin\n");
572 EXTRACTOR_IPC_channel_destroy_ (channel); 580 EXTRACTOR_IPC_channel_destroy_ (channel);
573 free (init); 581 free (init);
574 return NULL; 582 return NULL;
575 } 583 }
576 free (init); 584 free (init);
577 return channel; 585 return channel;
578} 586}
579 587
588
580/** 589/**
581 * Destroy communication channel with a plugin/process. Also 590 * Destroy communication channel with a plugin/process. Also
582 * destroys the process. 591 * destroys the process.
@@ -606,6 +615,7 @@ EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel)
606 free (channel); 615 free (channel);
607} 616}
608 617
618
609/** 619/**
610 * Send data via the given IPC channel (blocking). 620 * Send data via the given IPC channel (blocking).
611 * 621 *
@@ -617,8 +627,8 @@ EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel)
617 */ 627 */
618ssize_t 628ssize_t
619EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel, 629EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
620 const void *data, 630 const void *data,
621 size_t size) 631 size_t size)
622{ 632{
623 DWORD written; 633 DWORD written;
624 DWORD err; 634 DWORD err;
@@ -644,7 +654,8 @@ EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
644 channel->ov_write.Pointer = 0; 654 channel->ov_write.Pointer = 0;
645 channel->ov_write.Internal = 0; 655 channel->ov_write.Internal = 0;
646 channel->ov_write.InternalHigh = 0; 656 channel->ov_write.InternalHigh = 0;
647 bresult = WriteFile (channel->cpipe_in, channel->old_buf, size, &written, &channel->ov_write); 657 bresult = WriteFile (channel->cpipe_in, channel->old_buf, size, &written,
658 &channel->ov_write);
648 659
649 if (bresult == TRUE) 660 if (bresult == TRUE)
650 { 661 {
@@ -682,9 +693,9 @@ EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
682 */ 693 */
683int 694int
684EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels, 695EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
685 unsigned int num_channels, 696 unsigned int num_channels,
686 EXTRACTOR_ChannelMessageProcessor proc, 697 EXTRACTOR_ChannelMessageProcessor proc,
687 void *proc_cls) 698 void *proc_cls)
688{ 699{
689 DWORD ms; 700 DWORD ms;
690 DWORD first_ready; 701 DWORD first_ready;
@@ -707,7 +718,8 @@ EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
707 if (WaitForSingleObject (channels[i]->ov_read.hEvent, 0) == WAIT_OBJECT_0) 718 if (WaitForSingleObject (channels[i]->ov_read.hEvent, 0) == WAIT_OBJECT_0)
708 { 719 {
709 ResetEvent (channels[i]->ov_read.hEvent); 720 ResetEvent (channels[i]->ov_read.hEvent);
710 bresult = ReadFile (channels[i]->cpipe_out, &i, 0, &bytes_read, &channels[i]->ov_read); 721 bresult = ReadFile (channels[i]->cpipe_out, &i, 0, &bytes_read,
722 &channels[i]->ov_read);
711 if (bresult == TRUE) 723 if (bresult == TRUE)
712 { 724 {
713 SetEvent (channels[i]->ov_read.hEvent); 725 SetEvent (channels[i]->ov_read.hEvent);
@@ -728,7 +740,7 @@ EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
728 740
729 ms = 500; 741 ms = 500;
730 first_ready = WaitForMultipleObjects (c, events, FALSE, ms); 742 first_ready = WaitForMultipleObjects (c, events, FALSE, ms);
731 if (first_ready == WAIT_TIMEOUT || first_ready == WAIT_FAILED) 743 if ((first_ready == WAIT_TIMEOUT) || (first_ready == WAIT_FAILED))
732 { 744 {
733 /* an error or timeout -> something's wrong or all plugins hung up */ 745 /* an error or timeout -> something's wrong or all plugins hung up */
734 closed_channel = 0; 746 closed_channel = 0;
@@ -765,37 +777,40 @@ EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
765 { 777 {
766 int ret; 778 int ret;
767 if (channels[i]->mdata_size == channels[i]->size) 779 if (channels[i]->mdata_size == channels[i]->size)
768 { 780 {
769 /* not enough space, need to grow allocation (if allowed) */ 781 /* not enough space, need to grow allocation (if allowed) */
770 if (MAX_META_DATA == channels[i]->mdata_size) 782 if (MAX_META_DATA == channels[i]->mdata_size)
771 { 783 {
772 LOG ("Inbound message from channel too large, aborting\n"); 784 LOG ("Inbound message from channel too large, aborting\n");
773 EXTRACTOR_IPC_channel_destroy_ (channels[i]); 785 EXTRACTOR_IPC_channel_destroy_ (channels[i]);
774 channels[i] = NULL; 786 channels[i] = NULL;
775 } 787 }
776 channels[i]->mdata_size *= 2; 788 channels[i]->mdata_size *= 2;
777 if (channels[i]->mdata_size > MAX_META_DATA) 789 if (channels[i]->mdata_size > MAX_META_DATA)
778 channels[i]->mdata_size = MAX_META_DATA; 790 channels[i]->mdata_size = MAX_META_DATA;
779 if (NULL == (ndata = realloc (channels[i]->mdata, 791 if (NULL == (ndata = realloc (channels[i]->mdata,
780 channels[i]->mdata_size))) 792 channels[i]->mdata_size)))
781 { 793 {
782 LOG_STRERROR ("realloc"); 794 LOG_STRERROR ("realloc");
783 EXTRACTOR_IPC_channel_destroy_ (channels[i]); 795 EXTRACTOR_IPC_channel_destroy_ (channels[i]);
784 channels[i] = NULL; 796 channels[i] = NULL;
785 } 797 }
786 channels[i]->mdata = ndata; 798 channels[i]->mdata = ndata;
787 } 799 }
788 bresult = ReadFile (channels[i]->cpipe_out, 800 bresult = ReadFile (channels[i]->cpipe_out,
789 &channels[i]->mdata[channels[i]->size], 801 &channels[i]->mdata[channels[i]->size],
790 channels[i]->mdata_size - channels[i]->size, &bytes_read, NULL); 802 channels[i]->mdata_size - channels[i]->size,
803 &bytes_read, NULL);
791 if (bresult) 804 if (bresult)
792 ret = EXTRACTOR_IPC_process_reply_ (channels[i]->plugin, 805 ret = EXTRACTOR_IPC_process_reply_ (channels[i]->plugin,
793 channels[i]->mdata, channels[i]->size + bytes_read, proc, proc_cls); 806 channels[i]->mdata,
794 if (!bresult || -1 == ret) 807 channels[i]->size + bytes_read,
808 proc, proc_cls);
809 if (! bresult || (-1 == ret))
795 { 810 {
796 DWORD error = GetLastError (); 811 DWORD error = GetLastError ();
797 SetErrnoFromWinError (error); 812 SetErrnoFromWinError (error);
798 if (!bresult) 813 if (! bresult)
799 LOG_STRERROR ("ReadFile"); 814 LOG_STRERROR ("ReadFile");
800 EXTRACTOR_IPC_channel_destroy_ (channels[i]); 815 EXTRACTOR_IPC_channel_destroy_ (channels[i]);
801 channels[i] = NULL; 816 channels[i] = NULL;
@@ -803,12 +818,10 @@ EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
803 else 818 else
804 { 819 {
805 memmove (channels[i]->mdata, &channels[i]->mdata[ret], 820 memmove (channels[i]->mdata, &channels[i]->mdata[ret],
806 channels[i]->size + bytes_read - ret); 821 channels[i]->size + bytes_read - ret);
807 channels[i]->size = channels[i]->size + bytes_read- ret; 822 channels[i]->size = channels[i]->size + bytes_read - ret;
808 } 823 }
809 } 824 }
810 } 825 }
811 return 1; 826 return 1;
812} 827}
813
814
diff --git a/src/main/extractor_logging.c b/src/main/extractor_logging.c
index b1518ae..17192fe 100644
--- a/src/main/extractor_logging.c
+++ b/src/main/extractor_logging.c
@@ -39,13 +39,15 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...)
39 va_list va; 39 va_list va;
40 40
41 fprintf (stderr, 41 fprintf (stderr,
42 "EXTRACTOR %s:%d ", 42 "EXTRACTOR %s:%d ",
43 file, line); 43 file, line);
44 va_start (va, format); 44 va_start (va, format);
45 vfprintf (stderr, format, va); 45 vfprintf (stderr, format, va);
46 va_end (va); 46 va_end (va);
47 fflush (stderr); 47 fflush (stderr);
48} 48}
49
50
49#endif 51#endif
50 52
51 53
@@ -57,7 +59,7 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...)
57 */ 59 */
58void 60void
59EXTRACTOR_abort_ (const char *file, 61EXTRACTOR_abort_ (const char *file,
60 int line) 62 int line)
61{ 63{
62#if DEBUG 64#if DEBUG
63 EXTRACTOR_log_ (file, line, "Assertion failed.\n"); 65 EXTRACTOR_log_ (file, line, "Assertion failed.\n");
@@ -65,4 +67,5 @@ EXTRACTOR_abort_ (const char *file,
65 ABORT (); 67 ABORT ();
66} 68}
67 69
70
68/* end of extractor_logging.c */ 71/* end of extractor_logging.c */
diff --git a/src/main/extractor_logging.h b/src/main/extractor_logging.h
index 5db9ae1..535a9a7 100644
--- a/src/main/extractor_logging.h
+++ b/src/main/extractor_logging.h
@@ -44,7 +44,7 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...);
44 * 44 *
45 * @param ... format string and arguments for fmt (printf-style) 45 * @param ... format string and arguments for fmt (printf-style)
46 */ 46 */
47#define LOG(...) EXTRACTOR_log_(__FILE__, __LINE__, __VA_ARGS__) 47#define LOG(...) EXTRACTOR_log_ (__FILE__, __LINE__, __VA_ARGS__)
48 48
49#else 49#else
50 50
@@ -64,7 +64,8 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...);
64 * 64 *
65 * @param syscall name of the syscall that failed 65 * @param syscall name of the syscall that failed
66 */ 66 */
67#define LOG_STRERROR(syscall) LOG("System call `%s' failed: %s\n", syscall, STRERROR (errno)) 67#define LOG_STRERROR(syscall) LOG ("System call `%s' failed: %s\n", syscall, \
68 STRERROR (errno))
68 69
69 70
70/** 71/**
@@ -74,7 +75,9 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...);
74 * @param syscall name of the syscall that failed 75 * @param syscall name of the syscall that failed
75 * @param filename name of the file that was involved 76 * @param filename name of the file that was involved
76 */ 77 */
77#define LOG_STRERROR_FILE(syscall,filename) LOG("System call `%s' failed for file `%s': %s\n", syscall, filename, STRERROR (errno)) 78#define LOG_STRERROR_FILE(syscall,filename) LOG ( \
79 "System call `%s' failed for file `%s': %s\n", syscall, filename, STRERROR ( \
80 errno))
78 81
79 82
80/** 83/**
@@ -85,7 +88,7 @@ EXTRACTOR_log_ (const char *file, int line, const char *format, ...);
85 */ 88 */
86void 89void
87EXTRACTOR_abort_ (const char *file, 90EXTRACTOR_abort_ (const char *file,
88 int line); 91 int line);
89 92
90 93
91/** 94/**
@@ -93,7 +96,8 @@ EXTRACTOR_abort_ (const char *file,
93 * 96 *
94 * @param cond assertion that must hold. 97 * @param cond assertion that must hold.
95 */ 98 */
96#define ASSERT(cond) do { if (! (cond)) EXTRACTOR_abort_ (__FILE__, __LINE__); } while (0) 99#define ASSERT(cond) do { if (! (cond)) EXTRACTOR_abort_ (__FILE__, __LINE__); \
100} while (0)
97 101
98 102
99#endif 103#endif
diff --git a/src/main/extractor_metatypes.c b/src/main/extractor_metatypes.c
index 41d1061..277a39f 100644
--- a/src/main/extractor_metatypes.c
+++ b/src/main/extractor_metatypes.c
@@ -30,7 +30,7 @@ struct MetaTypeDescription
30 * Short (typically 1-word) description. 30 * Short (typically 1-word) description.
31 */ 31 */
32 const char *short_description; 32 const char *short_description;
33 33
34 /** 34 /**
35 * More detailed description. 35 * More detailed description.
36 */ 36 */
@@ -48,7 +48,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
48 { gettext_noop ("mimetype"), 48 { gettext_noop ("mimetype"),
49 gettext_noop ("mime type") }, 49 gettext_noop ("mime type") },
50 { gettext_noop ("embedded filename"), 50 { gettext_noop ("embedded filename"),
51 gettext_noop ("filename that was embedded (not necessarily the current filename)") }, 51 gettext_noop (
52 "filename that was embedded (not necessarily the current filename)") },
52 { gettext_noop ("comment"), 53 { gettext_noop ("comment"),
53 gettext_noop ("comment about the content") }, 54 gettext_noop ("comment about the content") },
54 { gettext_noop ("title"), 55 { gettext_noop ("title"),
@@ -62,15 +63,16 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
62 gettext_noop ("chapter number") }, 63 gettext_noop ("chapter number") },
63 { gettext_noop ("journal name"), 64 { gettext_noop ("journal name"),
64 gettext_noop ("journal or magazine the work was published in") }, 65 gettext_noop ("journal or magazine the work was published in") },
65 { gettext_noop ("journal volume"), 66 { gettext_noop ("journal volume"),
66 gettext_noop ("volume of a journal or multi-volume book") }, 67 gettext_noop ("volume of a journal or multi-volume book") },
67 /* 10 */ 68 /* 10 */
68 { gettext_noop ("journal number"), 69 { gettext_noop ("journal number"),
69 gettext_noop ("number of a journal, magazine or tech-report") }, 70 gettext_noop ("number of a journal, magazine or tech-report") },
70 { gettext_noop ("page count"), 71 { gettext_noop ("page count"),
71 gettext_noop ("total number of pages of the work") }, 72 gettext_noop ("total number of pages of the work") },
72 { gettext_noop ("page range"), 73 { gettext_noop ("page range"),
73 gettext_noop ("page numbers of the publication in the respective journal or book") }, 74 gettext_noop (
75 "page numbers of the publication in the respective journal or book") },
74 { gettext_noop ("author name"), 76 { gettext_noop ("author name"),
75 gettext_noop ("name of the author(s)") }, 77 gettext_noop ("name of the author(s)") },
76 { gettext_noop ("author email"), 78 { gettext_noop ("author email"),
@@ -83,20 +85,25 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
83 { gettext_noop ("publisher's address"), 85 { gettext_noop ("publisher's address"),
84 gettext_noop ("Address of the publisher (often only the city)") }, 86 gettext_noop ("Address of the publisher (often only the city)") },
85 { gettext_noop ("publishing institution"), 87 { gettext_noop ("publishing institution"),
86 gettext_noop ("institution that was involved in the publishing, but not necessarily the publisher") }, 88 gettext_noop (
89 "institution that was involved in the publishing, but not necessarily the publisher") },
87 { gettext_noop ("publication series"), 90 { gettext_noop ("publication series"),
88 gettext_noop ("series of books the book was published in") }, 91 gettext_noop ("series of books the book was published in") },
89 /* 20 */ 92 /* 20 */
90 { gettext_noop ("publication type"), 93 { gettext_noop ("publication type"),
91 gettext_noop ("type of the tech-report") }, 94 gettext_noop ("type of the tech-report") },
92 { gettext_noop ("publication year"), 95 { gettext_noop ("publication year"),
93 gettext_noop ("year of publication (or, if unpublished, the year of creation)") }, 96 gettext_noop (
97 "year of publication (or, if unpublished, the year of creation)") },
94 { gettext_noop ("publication month"), 98 { gettext_noop ("publication month"),
95 gettext_noop ("month of publication (or, if unpublished, the month of creation)") }, 99 gettext_noop (
100 "month of publication (or, if unpublished, the month of creation)") },
96 { gettext_noop ("publication day"), 101 { gettext_noop ("publication day"),
97 gettext_noop ("day of publication (or, if unpublished, the day of creation), relative to the given month") }, 102 gettext_noop (
103 "day of publication (or, if unpublished, the day of creation), relative to the given month") },
98 { gettext_noop ("publication date"), 104 { gettext_noop ("publication date"),
99 gettext_noop ("date of publication (or, if unpublished, the date of creation)") }, 105 gettext_noop (
106 "date of publication (or, if unpublished, the date of creation)") },
100 /* 25 */ 107 /* 25 */
101 { gettext_noop ("bibtex eprint"), 108 { gettext_noop ("bibtex eprint"),
102 gettext_noop ("specification of an electronic publication") }, 109 gettext_noop ("specification of an electronic publication") },
@@ -107,7 +114,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
107 { gettext_noop ("creation time"), 114 { gettext_noop ("creation time"),
108 gettext_noop ("time and date of creation") }, 115 gettext_noop ("time and date of creation") },
109 { gettext_noop ("URL"), 116 { gettext_noop ("URL"),
110 gettext_noop ("universal resource location (where the work is made available)") }, 117 gettext_noop (
118 "universal resource location (where the work is made available)") },
111 /* 30 */ 119 /* 30 */
112 { gettext_noop ("URI"), 120 { gettext_noop ("URI"),
113 gettext_noop ("universal resource identifier") }, 121 gettext_noop ("universal resource identifier") },
@@ -120,7 +128,7 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
120 { gettext_noop ("SHA-0"), 128 { gettext_noop ("SHA-0"),
121 gettext_noop ("SHA-0 hash") }, 129 gettext_noop ("SHA-0 hash") },
122 /* 35 */ 130 /* 35 */
123 { gettext_noop ("SHA-1"), 131 { gettext_noop ("SHA-1"),
124 gettext_noop ("SHA-1 hash") }, 132 gettext_noop ("SHA-1 hash") },
125 { gettext_noop ("RipeMD160"), 133 { gettext_noop ("RipeMD160"),
126 gettext_noop ("RipeMD150 hash") }, 134 gettext_noop ("RipeMD150 hash") },
@@ -135,7 +143,7 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
135 gettext_noop ("GPS longitude") }, 143 gettext_noop ("GPS longitude") },
136 { gettext_noop ("city"), 144 { gettext_noop ("city"),
137 gettext_noop ("name of the city where the document originated") }, 145 gettext_noop ("name of the city where the document originated") },
138 { gettext_noop ("sublocation"), 146 { gettext_noop ("sublocation"),
139 gettext_noop ("more specific location of the geographic origin") }, 147 gettext_noop ("more specific location of the geographic origin") },
140 { gettext_noop ("country"), 148 { gettext_noop ("country"),
141 gettext_noop ("name of the country where the document originated") }, 149 gettext_noop ("name of the country where the document originated") },
@@ -169,7 +177,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
169 { gettext_noop ("created by software"), 177 { gettext_noop ("created by software"),
170 gettext_noop ("name of the software that created the document") }, 178 gettext_noop ("name of the software that created the document") },
171 { gettext_noop ("unknown date"), 179 { gettext_noop ("unknown date"),
172 gettext_noop ("ambiguous date (could specify creation time, modification time or access time)") }, 180 gettext_noop (
181 "ambiguous date (could specify creation time, modification time or access time)") },
173 { gettext_noop ("creation date"), 182 { gettext_noop ("creation date"),
174 gettext_noop ("date the document was created") }, 183 gettext_noop ("date the document was created") },
175 { gettext_noop ("modification date"), 184 { gettext_noop ("modification date"),
@@ -189,7 +198,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
189 { gettext_noop ("revision history"), 198 { gettext_noop ("revision history"),
190 gettext_noop ("information about the revision history") }, 199 gettext_noop ("information about the revision history") },
191 { gettext_noop ("embedded file size"), 200 { gettext_noop ("embedded file size"),
192 gettext_noop ("size of the contents of the container as embedded in the file") }, 201 gettext_noop (
202 "size of the contents of the container as embedded in the file") },
193 { gettext_noop ("file type"), 203 { gettext_noop ("file type"),
194 gettext_noop ("standard Macintosh Finder file type information") }, 204 gettext_noop ("standard Macintosh Finder file type information") },
195 { gettext_noop ("creator"), 205 { gettext_noop ("creator"),
@@ -213,9 +223,11 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
213 { gettext_noop ("provides"), 223 { gettext_noop ("provides"),
214 gettext_noop ("functionality provided by this package") }, 224 gettext_noop ("functionality provided by this package") },
215 { gettext_noop ("recommendations"), 225 { gettext_noop ("recommendations"),
216 gettext_noop ("packages recommended for installation in conjunction with this package") }, 226 gettext_noop (
227 "packages recommended for installation in conjunction with this package") },
217 { gettext_noop ("suggestions"), 228 { gettext_noop ("suggestions"),
218 gettext_noop ("packages suggested for installation in conjunction with this package") }, 229 gettext_noop (
230 "packages suggested for installation in conjunction with this package") },
219 { gettext_noop ("maintainer"), 231 { gettext_noop ("maintainer"),
220 gettext_noop ("name of the maintainer") }, 232 gettext_noop ("name of the maintainer") },
221 /* 80 */ 233 /* 80 */
@@ -228,208 +240,218 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
228 { gettext_noop ("target architecture"), 240 { gettext_noop ("target architecture"),
229 gettext_noop ("hardware architecture the contents can be used for") }, 241 gettext_noop ("hardware architecture the contents can be used for") },
230 { gettext_noop ("pre-dependency"), 242 { gettext_noop ("pre-dependency"),
231 gettext_noop ("dependency that must be satisfied before installation") }, 243 gettext_noop ("dependency that must be satisfied before installation") },
232 /* 85 */ 244 /* 85 */
233 { gettext_noop ("license"), 245 { gettext_noop ("license"),
234 gettext_noop ("applicable copyright license") }, 246 gettext_noop ("applicable copyright license") },
235 { gettext_noop ("distribution"), 247 { gettext_noop ("distribution"),
236 gettext_noop ("distribution the package is a part of") }, 248 gettext_noop ("distribution the package is a part of") },
237 { gettext_noop ("build host"), 249 { gettext_noop ("build host"),
238 gettext_noop ("machine the package was build on") }, 250 gettext_noop ("machine the package was build on") },
239 { gettext_noop ("vendor"), 251 { gettext_noop ("vendor"),
240 gettext_noop ("name of the software vendor") }, 252 gettext_noop ("name of the software vendor") },
241 { gettext_noop ("target operating system"), 253 { gettext_noop ("target operating system"),
242 gettext_noop ("operating system for which this package was made") }, 254 gettext_noop ("operating system for which this package was made") },
243 /* 90 */ 255 /* 90 */
244 { gettext_noop ("software version"), 256 { gettext_noop ("software version"),
245 gettext_noop ("version of the software contained in the file") }, 257 gettext_noop ("version of the software contained in the file") },
246 { gettext_noop ("target platform"), 258 { gettext_noop ("target platform"),
247 gettext_noop ("name of the architecture, operating system and distribution this package is for") }, 259 gettext_noop (
260 "name of the architecture, operating system and distribution this package is for") },
248 { gettext_noop ("resource type"), 261 { gettext_noop ("resource type"),
249 gettext_noop ("categorization of the nature of the resource that is more specific than the file format") }, 262 gettext_noop (
263 "categorization of the nature of the resource that is more specific than the file format") },
250 { gettext_noop ("library search path"), 264 { gettext_noop ("library search path"),
251 gettext_noop ("path in the file system to be considered when looking for required libraries") }, 265 gettext_noop (
266 "path in the file system to be considered when looking for required libraries") },
252 { gettext_noop ("library dependency"), 267 { gettext_noop ("library dependency"),
253 gettext_noop ("name of a library that this file depends on") }, 268 gettext_noop ("name of a library that this file depends on") },
254 /* 95 */ 269 /* 95 */
255 { gettext_noop ("camera make"), 270 { gettext_noop ("camera make"),
256 gettext_noop ("camera make") }, 271 gettext_noop ("camera make") },
257 { gettext_noop ("camera model"), 272 { gettext_noop ("camera model"),
258 gettext_noop ("camera model") }, 273 gettext_noop ("camera model") },
259 { gettext_noop ("exposure"), 274 { gettext_noop ("exposure"),
260 gettext_noop ("exposure") }, 275 gettext_noop ("exposure") },
261 { gettext_noop ("aperture"), 276 { gettext_noop ("aperture"),
262 gettext_noop ("aperture") }, 277 gettext_noop ("aperture") },
263 { gettext_noop ("exposure bias"), 278 { gettext_noop ("exposure bias"),
264 gettext_noop ("exposure bias") }, 279 gettext_noop ("exposure bias") },
265 /* 100 */ 280 /* 100 */
266 { gettext_noop ("flash"), 281 { gettext_noop ("flash"),
267 gettext_noop ("flash") }, 282 gettext_noop ("flash") },
268 { gettext_noop ("flash bias"), 283 { gettext_noop ("flash bias"),
269 gettext_noop ("flash bias") }, 284 gettext_noop ("flash bias") },
270 { gettext_noop ("focal length"), 285 { gettext_noop ("focal length"),
271 gettext_noop ("focal length") }, 286 gettext_noop ("focal length") },
272 { gettext_noop ("focal length 35mm"), 287 { gettext_noop ("focal length 35mm"),
273 gettext_noop ("focal length 35mm") }, 288 gettext_noop ("focal length 35mm") },
274 { gettext_noop ("iso speed"), 289 { gettext_noop ("iso speed"),
275 gettext_noop ("iso speed") }, 290 gettext_noop ("iso speed") },
276 /* 105 */ 291 /* 105 */
277 { gettext_noop ("exposure mode"), 292 { gettext_noop ("exposure mode"),
278 gettext_noop ("exposure mode") }, 293 gettext_noop ("exposure mode") },
279 { gettext_noop ("metering mode"), 294 { gettext_noop ("metering mode"),
280 gettext_noop ("metering mode") }, 295 gettext_noop ("metering mode") },
281 { gettext_noop ("macro mode"), 296 { gettext_noop ("macro mode"),
282 gettext_noop ("macro mode") }, 297 gettext_noop ("macro mode") },
283 { gettext_noop ("image quality"), 298 { gettext_noop ("image quality"),
284 gettext_noop ("image quality") }, 299 gettext_noop ("image quality") },
285 { gettext_noop ("white balance"), 300 { gettext_noop ("white balance"),
286 gettext_noop ("white balance") }, 301 gettext_noop ("white balance") },
287 /* 110 */ 302 /* 110 */
288 { gettext_noop ("orientation"), 303 { gettext_noop ("orientation"),
289 gettext_noop ("orientation") }, 304 gettext_noop ("orientation") },
290 { gettext_noop ("magnification"), 305 { gettext_noop ("magnification"),
291 gettext_noop ("magnification") }, 306 gettext_noop ("magnification") },
292 { gettext_noop ("image dimensions"), 307 { gettext_noop ("image dimensions"),
293 gettext_noop ("size of the image in pixels (width times height)") }, 308 gettext_noop ("size of the image in pixels (width times height)") },
294 { gettext_noop ("produced by software"), 309 { gettext_noop ("produced by software"),
295 gettext_noop ("produced by software") }, /* what is the exact difference between the software 310 gettext_noop ("produced by software") }, /* what is the exact difference between the software
296 creator and the software producer? PDF and DVI 311 creator and the software producer? PDF and DVI
297 both have this distinction (i.e., Writer vs. 312 both have this distinction (i.e., Writer vs.
298 OpenOffice) */ 313 OpenOffice) */
299 { gettext_noop ("thumbnail"), 314 { gettext_noop ("thumbnail"),
300 gettext_noop ("smaller version of the image for previewing") }, 315 gettext_noop ("smaller version of the image for previewing") },
301 /* 115 */ 316 /* 115 */
302 { gettext_noop ("image resolution"), 317 { gettext_noop ("image resolution"),
303 gettext_noop ("resolution in dots per inch") }, 318 gettext_noop ("resolution in dots per inch") },
304 { gettext_noop ("source"), 319 { gettext_noop ("source"),
305 gettext_noop ("Originating entity") }, 320 gettext_noop ("Originating entity") },
306 { gettext_noop ("character set"), 321 { gettext_noop ("character set"),
307 gettext_noop ("character encoding used") }, 322 gettext_noop ("character encoding used") },
308 { gettext_noop ("line count"), 323 { gettext_noop ("line count"),
309 gettext_noop ("number of lines") }, 324 gettext_noop ("number of lines") },
310 { gettext_noop ("paragraph count"), 325 { gettext_noop ("paragraph count"),
311 gettext_noop ("number of paragraphs") }, 326 gettext_noop ("number of paragraphs") },
312 /* 120 */ 327 /* 120 */
313 { gettext_noop ("word count"), 328 { gettext_noop ("word count"),
314 gettext_noop ("number of words") }, 329 gettext_noop ("number of words") },
315 { gettext_noop ("character count"), 330 { gettext_noop ("character count"),
316 gettext_noop ("number of characters") }, 331 gettext_noop ("number of characters") },
317 { gettext_noop ("page orientation"), 332 { gettext_noop ("page orientation"),
318 gettext_noop ("page orientation") }, 333 gettext_noop ("page orientation") },
319 { gettext_noop ("paper size"), 334 { gettext_noop ("paper size"),
320 gettext_noop ("paper size") }, 335 gettext_noop ("paper size") },
321 { gettext_noop ("template"), 336 { gettext_noop ("template"),
322 gettext_noop ("template the document uses or is based on") }, 337 gettext_noop ("template the document uses or is based on") },
323 /* 125 */ 338 /* 125 */
324 { gettext_noop ("company"), 339 { gettext_noop ("company"),
325 gettext_noop ("company") }, 340 gettext_noop ("company") },
326 { gettext_noop ("manager"), 341 { gettext_noop ("manager"),
327 gettext_noop ("manager") }, 342 gettext_noop ("manager") },
328 { gettext_noop ("revision number"), 343 { gettext_noop ("revision number"),
329 gettext_noop ("revision number") }, 344 gettext_noop ("revision number") },
330 { gettext_noop ("duration"), 345 { gettext_noop ("duration"),
331 gettext_noop ("play time for the medium") }, 346 gettext_noop ("play time for the medium") },
332 { gettext_noop ("album"), 347 { gettext_noop ("album"),
333 gettext_noop ("name of the album") }, 348 gettext_noop ("name of the album") },
334 /* 130 */ 349 /* 130 */
335 { gettext_noop ("artist"), 350 { gettext_noop ("artist"),
336 gettext_noop ("name of the artist or band") }, 351 gettext_noop ("name of the artist or band") },
337 { gettext_noop ("genre"), 352 { gettext_noop ("genre"),
338 gettext_noop ("genre") }, 353 gettext_noop ("genre") },
339 { gettext_noop ("track number"), 354 { gettext_noop ("track number"),
340 gettext_noop ("original number of the track on the distribution medium") }, 355 gettext_noop ("original number of the track on the distribution medium") },
341 { gettext_noop ("disk number"), 356 { gettext_noop ("disk number"),
342 gettext_noop ("number of the disk in a multi-disk (or volume) distribution") }, 357 gettext_noop (
358 "number of the disk in a multi-disk (or volume) distribution") },
343 { gettext_noop ("performer"), 359 { gettext_noop ("performer"),
344 gettext_noop ("The artist(s) who performed the work (conductor, orchestra, soloists, actor, etc.)") }, 360 gettext_noop (
361 "The artist(s) who performed the work (conductor, orchestra, soloists, actor, etc.)") },
345 /* 135 */ 362 /* 135 */
346 { gettext_noop ("contact"), 363 { gettext_noop ("contact"),
347 gettext_noop ("Contact information for the creator or distributor") }, 364 gettext_noop ("Contact information for the creator or distributor") },
348 { gettext_noop ("song version"), 365 { gettext_noop ("song version"),
349 gettext_noop ("name of the version of the song (i.e. remix information)") }, 366 gettext_noop ("name of the version of the song (i.e. remix information)") },
350 { gettext_noop ("picture"), 367 { gettext_noop ("picture"),
351 gettext_noop ("associated misc. picture") }, 368 gettext_noop ("associated misc. picture") },
352 { gettext_noop ("cover picture"), 369 { gettext_noop ("cover picture"),
353 gettext_noop ("picture of the cover of the distribution medium") }, 370 gettext_noop ("picture of the cover of the distribution medium") },
354 { gettext_noop ("contributor picture"), 371 { gettext_noop ("contributor picture"),
355 gettext_noop ("picture of one of the contributors") }, 372 gettext_noop ("picture of one of the contributors") },
356 /* 140 */ 373 /* 140 */
357 { gettext_noop ("event picture"), 374 { gettext_noop ("event picture"),
358 gettext_noop ("picture of an associated event") }, 375 gettext_noop ("picture of an associated event") },
359 { gettext_noop ("logo"), 376 { gettext_noop ("logo"),
360 gettext_noop ("logo of an associated organization") }, 377 gettext_noop ("logo of an associated organization") },
361 { gettext_noop ("broadcast television system"), 378 { gettext_noop ("broadcast television system"),
362 gettext_noop ("name of the television system for which the data is coded") }, 379 gettext_noop (
380 "name of the television system for which the data is coded") },
363 { gettext_noop ("source device"), 381 { gettext_noop ("source device"),
364 gettext_noop ("device used to create the object") }, 382 gettext_noop ("device used to create the object") },
365 { gettext_noop ("disclaimer"), 383 { gettext_noop ("disclaimer"),
366 gettext_noop ("legal disclaimer") }, 384 gettext_noop ("legal disclaimer") },
367 /* 145 */ 385 /* 145 */
368 { gettext_noop ("warning"), 386 { gettext_noop ("warning"),
369 gettext_noop ("warning about the nature of the content") }, 387 gettext_noop ("warning about the nature of the content") },
370 { gettext_noop ("page order"), 388 { gettext_noop ("page order"),
371 gettext_noop ("order of the pages") }, 389 gettext_noop ("order of the pages") },
372 { gettext_noop ("writer"), 390 { gettext_noop ("writer"),
373 gettext_noop ("contributing writer") }, 391 gettext_noop ("contributing writer") },
374 { gettext_noop ("product version"), 392 { gettext_noop ("product version"),
375 gettext_noop ("product version") }, 393 gettext_noop ("product version") },
376 { gettext_noop ("contributor"), 394 { gettext_noop ("contributor"),
377 gettext_noop ("name of a contributor") }, 395 gettext_noop ("name of a contributor") },
378 /* 150 */ 396 /* 150 */
379 { gettext_noop ("movie director"), 397 { gettext_noop ("movie director"),
380 gettext_noop ("name of the director") }, 398 gettext_noop ("name of the director") },
381 { gettext_noop ("network"), 399 { gettext_noop ("network"),
382 gettext_noop ("name of the broadcasting network or station") }, 400 gettext_noop ("name of the broadcasting network or station") },
383 { gettext_noop ("show"), 401 { gettext_noop ("show"),
384 gettext_noop ("name of the show") }, 402 gettext_noop ("name of the show") },
385 { gettext_noop ("chapter name"), 403 { gettext_noop ("chapter name"),
386 gettext_noop ("name of the chapter") }, 404 gettext_noop ("name of the chapter") },
387 { gettext_noop ("song count"), 405 { gettext_noop ("song count"),
388 gettext_noop ("number of songs") }, 406 gettext_noop ("number of songs") },
389 /* 155 */ 407 /* 155 */
390 { gettext_noop ("starting song"), 408 { gettext_noop ("starting song"),
391 gettext_noop ("number of the first song to play") }, 409 gettext_noop ("number of the first song to play") },
392 { gettext_noop ("play counter"), 410 { gettext_noop ("play counter"),
393 gettext_noop ("number of times the media has been played") }, 411 gettext_noop ("number of times the media has been played") },
394 { gettext_noop ("conductor"), 412 { gettext_noop ("conductor"),
395 gettext_noop ("name of the conductor") }, 413 gettext_noop ("name of the conductor") },
396 { gettext_noop ("interpretation"), 414 { gettext_noop ("interpretation"),
397 gettext_noop ("information about the people behind interpretations of an existing piece") }, 415 gettext_noop (
416 "information about the people behind interpretations of an existing piece") },
398 { gettext_noop ("composer"), 417 { gettext_noop ("composer"),
399 gettext_noop ("name of the composer") }, 418 gettext_noop ("name of the composer") },
400 /* 160 */ 419 /* 160 */
401 { gettext_noop ("beats per minute"), 420 { gettext_noop ("beats per minute"),
402 gettext_noop ("beats per minute") }, 421 gettext_noop ("beats per minute") },
403 { gettext_noop ("encoded by"), 422 { gettext_noop ("encoded by"),
404 gettext_noop ("name of person or organization that encoded the file") }, 423 gettext_noop ("name of person or organization that encoded the file") },
405 { gettext_noop ("original title"), 424 { gettext_noop ("original title"),
406 gettext_noop ("title of the original work") }, 425 gettext_noop ("title of the original work") },
407 { gettext_noop ("original artist"), 426 { gettext_noop ("original artist"),
408 gettext_noop ("name of the original artist") }, 427 gettext_noop ("name of the original artist") },
409 { gettext_noop ("original writer"), 428 { gettext_noop ("original writer"),
410 gettext_noop ("name of the original lyricist or writer") }, 429 gettext_noop ("name of the original lyricist or writer") },
411 /* 165 */ 430 /* 165 */
412 { gettext_noop ("original release year"), 431 { gettext_noop ("original release year"),
413 gettext_noop ("year of the original release") }, 432 gettext_noop ("year of the original release") },
414 { gettext_noop ("original performer"), 433 { gettext_noop ("original performer"),
415 gettext_noop ("name of the original performer") }, 434 gettext_noop ("name of the original performer") },
416 { gettext_noop ("lyrics"), 435 { gettext_noop ("lyrics"),
417 gettext_noop ("lyrics of the song or text description of vocal activities") }, 436 gettext_noop (
437 "lyrics of the song or text description of vocal activities") },
418 { gettext_noop ("popularity"), 438 { gettext_noop ("popularity"),
419 gettext_noop ("information about the file's popularity") }, 439 gettext_noop ("information about the file's popularity") },
420 { gettext_noop ("licensee"), 440 { gettext_noop ("licensee"),
421 gettext_noop ("name of the owner or licensee of the file") }, 441 gettext_noop ("name of the owner or licensee of the file") },
422 /* 170 */ 442 /* 170 */
423 { gettext_noop ("musician credit list"), 443 { gettext_noop ("musician credit list"),
424 gettext_noop ("names of contributing musicians") }, 444 gettext_noop ("names of contributing musicians") },
425 { gettext_noop ("mood"), 445 { gettext_noop ("mood"),
426 gettext_noop ("keywords reflecting the mood of the piece") }, 446 gettext_noop ("keywords reflecting the mood of the piece") },
427 { gettext_noop ("subtitle"), 447 { gettext_noop ("subtitle"),
428 gettext_noop ("subtitle of this part") }, 448 gettext_noop ("subtitle of this part") },
429 { gettext_noop ("display type"), 449 { gettext_noop ("display type"),
430 gettext_noop ("what rendering method should be used to display this item") }, 450 gettext_noop (
451 "what rendering method should be used to display this item") },
431 { gettext_noop ("full data"), 452 { gettext_noop ("full data"),
432 gettext_noop ("entry that contains the full, original binary data (not really meta data)") }, 453 gettext_noop (
454 "entry that contains the full, original binary data (not really meta data)") },
433 /* 175 */ 455 /* 175 */
434 { gettext_noop ("rating"), 456 { gettext_noop ("rating"),
435 gettext_noop ("rating of the content") }, 457 gettext_noop ("rating of the content") },
@@ -437,9 +459,9 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
437 gettext_noop ("organization") }, 459 gettext_noop ("organization") },
438 { gettext_noop ("ripper"), /* any difference to "encoded by"? */ 460 { gettext_noop ("ripper"), /* any difference to "encoded by"? */
439 gettext_noop ("ripper") }, 461 gettext_noop ("ripper") },
440 { gettext_noop ("producer"), 462 { gettext_noop ("producer"),
441 gettext_noop ("producer") }, 463 gettext_noop ("producer") },
442 { gettext_noop ("group"), 464 { gettext_noop ("group"),
443 gettext_noop ("name of the group or band") }, 465 gettext_noop ("name of the group or band") },
444 /* 180 */ 466 /* 180 */
445 { gettext_noop ("original filename"), 467 { gettext_noop ("original filename"),
@@ -460,7 +482,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
460 { gettext_noop ("bitrate"), 482 { gettext_noop ("bitrate"),
461 gettext_noop ("exact or average bitrate in bits/s") }, 483 gettext_noop ("exact or average bitrate in bits/s") },
462 { gettext_noop ("nominal bitrate"), 484 { gettext_noop ("nominal bitrate"),
463 gettext_noop ("nominal bitrate in bits/s. The actual bitrate might be different from this target bitrate.") }, 485 gettext_noop (
486 "nominal bitrate in bits/s. The actual bitrate might be different from this target bitrate.") },
464 { gettext_noop ("minimum bitrate"), 487 { gettext_noop ("minimum bitrate"),
465 gettext_noop ("minimum bitrate in bits/s") }, 488 gettext_noop ("minimum bitrate in bits/s") },
466 /* 190 */ 489 /* 190 */
@@ -484,25 +507,32 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
484 { gettext_noop ("reference level"), 507 { gettext_noop ("reference level"),
485 gettext_noop ("reference level of track and album gain values") }, 508 gettext_noop ("reference level of track and album gain values") },
486 { gettext_noop ("location name"), 509 { gettext_noop ("location name"),
487 gettext_noop ("human readable descriptive location of where the media has been recorded or produced") }, 510 gettext_noop (
511 "human readable descriptive location of where the media has been recorded or produced") },
488 /* 200 */ 512 /* 200 */
489 { gettext_noop ("location elevation"), 513 { gettext_noop ("location elevation"),
490 gettext_noop ("geo elevation of where the media has been recorded or produced in meters according to WGS84 (zero is average sea level)") }, 514 gettext_noop (
515 "geo elevation of where the media has been recorded or produced in meters according to WGS84 (zero is average sea level)") },
491 { gettext_noop ("location horizontal error"), 516 { gettext_noop ("location horizontal error"),
492 gettext_noop ("represents the expected error on the horizontal positioning in meters") }, 517 gettext_noop (
518 "represents the expected error on the horizontal positioning in meters") },
493 { gettext_noop ("location movement speed"), 519 { gettext_noop ("location movement speed"),
494 gettext_noop ("speed of the capturing device when performing the capture. Represented in m/s") }, 520 gettext_noop (
521 "speed of the capturing device when performing the capture. Represented in m/s") },
495 { gettext_noop ("location movement direction"), 522 { gettext_noop ("location movement direction"),
496 gettext_noop ("indicates the movement direction of the device performing the capture of a media. It is represented as degrees in floating point representation, 0 means the geographic north, and increases clockwise") }, 523 gettext_noop (
524 "indicates the movement direction of the device performing the capture of a media. It is represented as degrees in floating point representation, 0 means the geographic north, and increases clockwise") },
497 { gettext_noop ("location capture direction"), 525 { gettext_noop ("location capture direction"),
498 gettext_noop ("indicates the direction the device is pointing to when capturing a media. It is represented as degrees in floating point representation, 0 means the geographic north, and increases clockwise") }, 526 gettext_noop (
527 "indicates the direction the device is pointing to when capturing a media. It is represented as degrees in floating point representation, 0 means the geographic north, and increases clockwise") },
499 /* 205 */ 528 /* 205 */
500 { gettext_noop ("show episode number"), 529 { gettext_noop ("show episode number"),
501 gettext_noop ("number of the episode within a season/show") }, 530 gettext_noop ("number of the episode within a season/show") },
502 { gettext_noop ("show season number"), 531 { gettext_noop ("show season number"),
503 gettext_noop ("number of the season of a show/series") }, 532 gettext_noop ("number of the season of a show/series") },
504 { gettext_noop ("grouping"), 533 { gettext_noop ("grouping"),
505 gettext_noop ("groups together media that are related and spans multiple tracks. An example are multiple pieces of a concerto") }, 534 gettext_noop (
535 "groups together media that are related and spans multiple tracks. An example are multiple pieces of a concerto") },
506 { gettext_noop ("device manufacturer"), 536 { gettext_noop ("device manufacturer"),
507 gettext_noop ("manufacturer of the device used to create the media") }, 537 gettext_noop ("manufacturer of the device used to create the media") },
508 { gettext_noop ("device model"), 538 { gettext_noop ("device model"),
@@ -552,7 +582,8 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
552 gettext_noop ("a preview of the file audio stream") }, 582 gettext_noop ("a preview of the file audio stream") },
553 583
554 { gettext_noop ("narinfo"), 584 { gettext_noop ("narinfo"),
555 gettext_noop ("file containing information about contents of a normalized archive (nar)") }, 585 gettext_noop (
586 "file containing information about contents of a normalized archive (nar)") },
556 /* 230 */ 587 /* 230 */
557 { gettext_noop ("nar"), 588 { gettext_noop ("nar"),
558 gettext_noop ("normalized archive") }, 589 gettext_noop ("normalized archive") },
@@ -562,9 +593,10 @@ static const struct MetaTypeDescription meta_type_descriptions[] = {
562}; 593};
563 594
564/** 595/**
565 * Total number of keyword types (for bounds-checking) 596 * Total number of keyword types (for bounds-checking)
566 */ 597 */
567#define HIGHEST_METATYPE_NUMBER (sizeof (meta_type_descriptions) / sizeof(*meta_type_descriptions)) 598#define HIGHEST_METATYPE_NUMBER (sizeof (meta_type_descriptions) \
599 / sizeof(*meta_type_descriptions))
568 600
569 601
570/** 602/**
diff --git a/src/main/extractor_plugin_main.c b/src/main/extractor_plugin_main.c
index 7b01140..fd4912f 100644
--- a/src/main/extractor_plugin_main.c
+++ b/src/main/extractor_plugin_main.c
@@ -116,8 +116,8 @@ struct ProcessingContext
116 */ 116 */
117static int64_t 117static int64_t
118plugin_env_seek (void *cls, 118plugin_env_seek (void *cls,
119 int64_t pos, 119 int64_t pos,
120 int whence) 120 int whence)
121{ 121{
122 struct ProcessingContext *pc = cls; 122 struct ProcessingContext *pc = cls;
123 struct SeekRequestMessage srm; 123 struct SeekRequestMessage srm;
@@ -127,117 +127,118 @@ plugin_env_seek (void *cls,
127 uint16_t wval; 127 uint16_t wval;
128 128
129 switch (whence) 129 switch (whence)
130 {
131 case SEEK_CUR:
132 if ( (pos < 0) && (pc->read_position < -pos) )
130 { 133 {
131 case SEEK_CUR: 134 LOG ("Invalid seek operation\n");
132 if ( (pos < 0) && (pc->read_position < - pos) ) 135 return -1;
133 { 136 }
134 LOG ("Invalid seek operation\n"); 137 if ((pos > 0) && ((pc->read_position + pos < pc->read_position) ||
135 return -1; 138 (pc->read_position + pos > pc->file_size)))
136 } 139 {
137 if ((pos > 0) && ((pc->read_position + pos < pc->read_position) || 140 LOG ("Invalid seek operation\n");
138 (pc->read_position + pos > pc->file_size))) 141 return -1;
139 { 142 }
140 LOG ("Invalid seek operation\n"); 143 npos = (uint64_t) (pc->read_position + pos);
141 return -1; 144 wval = 0;
142 } 145 break;
143 npos = (uint64_t) (pc->read_position + pos); 146 case SEEK_END:
144 wval = 0; 147 if (pos > 0)
145 break; 148 {
146 case SEEK_END: 149 LOG ("Invalid seek operation\n");
147 if (pos > 0) 150 return -1;
148 { 151 }
149 LOG ("Invalid seek operation\n"); 152 if (UINT64_MAX == pc->file_size)
150 return -1; 153 {
151 } 154 wval = 2;
152 if (UINT64_MAX == pc->file_size) 155 npos = (uint64_t) -pos;
153 {
154 wval = 2;
155 npos = (uint64_t) - pos;
156 break;
157 }
158 pos = (int64_t) (pc->file_size + pos);
159 /* fall-through! */
160 case SEEK_SET:
161 if ( (pos < 0) || (pc->file_size < pos) )
162 {
163 LOG ("Invalid seek operation\n");
164 return -1;
165 }
166 npos = (uint64_t) pos;
167 wval = 0;
168 break; 156 break;
169 default: 157 }
158 pos = (int64_t) (pc->file_size + pos);
159 /* fall-through! */
160 case SEEK_SET:
161 if ( (pos < 0) || (pc->file_size < pos) )
162 {
170 LOG ("Invalid seek operation\n"); 163 LOG ("Invalid seek operation\n");
171 return -1; 164 return -1;
172 } 165 }
166 npos = (uint64_t) pos;
167 wval = 0;
168 break;
169 default:
170 LOG ("Invalid seek operation\n");
171 return -1;
172 }
173 if ( (pc->shm_off <= npos) && 173 if ( (pc->shm_off <= npos) &&
174 (pc->shm_off + pc->shm_ready_bytes > npos) && 174 (pc->shm_off + pc->shm_ready_bytes > npos) &&
175 (0 == wval) ) 175 (0 == wval) )
176 { 176 {
177 pc->read_position = npos; 177 pc->read_position = npos;
178 return (int64_t) npos; 178 return (int64_t) npos;
179 } 179 }
180 /* need to seek */ 180 /* need to seek */
181 srm.opcode = MESSAGE_SEEK; 181 srm.opcode = MESSAGE_SEEK;
182 srm.reserved = 0; 182 srm.reserved = 0;
183 srm.whence = wval; 183 srm.whence = wval;
184 srm.requested_bytes = pc->shm_map_size; 184 srm.requested_bytes = pc->shm_map_size;
185 if (0 == wval) 185 if (0 == wval)
186 { 186 {
187 if (srm.requested_bytes > pc->file_size - npos) 187 if (srm.requested_bytes > pc->file_size - npos)
188 srm.requested_bytes = pc->file_size - npos; 188 srm.requested_bytes = pc->file_size - npos;
189 } 189 }
190 else 190 else
191 { 191 {
192 srm.requested_bytes = npos; 192 srm.requested_bytes = npos;
193 } 193 }
194 srm.file_offset = npos; 194 srm.file_offset = npos;
195 if (-1 == EXTRACTOR_write_all_ (pc->out, &srm, sizeof (srm))) 195 if (-1 == EXTRACTOR_write_all_ (pc->out, &srm, sizeof (srm)))
196 { 196 {
197 LOG ("Failed to send MESSAGE_SEEK\n"); 197 LOG ("Failed to send MESSAGE_SEEK\n");
198 return -1; 198 return -1;
199 } 199 }
200 if (-1 == 200 if (-1 ==
201 EXTRACTOR_read_all_ (pc->in, 201 EXTRACTOR_read_all_ (pc->in,
202 &reply, sizeof (reply))) 202 &reply, sizeof (reply)))
203 { 203 {
204 LOG ("Plugin `%s' failed to read response to MESSAGE_SEEK\n", 204 LOG ("Plugin `%s' failed to read response to MESSAGE_SEEK\n",
205 pc->plugin->short_libname); 205 pc->plugin->short_libname);
206 return -1; 206 return -1;
207 } 207 }
208 if (MESSAGE_UPDATED_SHM != reply) 208 if (MESSAGE_UPDATED_SHM != reply)
209 { 209 {
210 LOG ("Unexpected reply %d to seek\n", reply); 210 LOG ("Unexpected reply %d to seek\n", reply);
211 return -1; /* was likely a MESSAGE_DISCARD_STATE */ 211 return -1; /* was likely a MESSAGE_DISCARD_STATE */
212 } 212 }
213 if (-1 == EXTRACTOR_read_all_ (pc->in, &um.reserved, sizeof (um) - 1)) 213 if (-1 == EXTRACTOR_read_all_ (pc->in, &um.reserved, sizeof (um) - 1))
214 { 214 {
215 LOG ("Failed to read MESSAGE_UPDATED_SHM\n"); 215 LOG ("Failed to read MESSAGE_UPDATED_SHM\n");
216 return -1; 216 return -1;
217 } 217 }
218 pc->shm_off = um.shm_off; 218 pc->shm_off = um.shm_off;
219 pc->shm_ready_bytes = um.shm_ready_bytes; 219 pc->shm_ready_bytes = um.shm_ready_bytes;
220 pc->file_size = um.file_size; 220 pc->file_size = um.file_size;
221 if (2 == wval) 221 if (2 == wval)
222 { 222 {
223 /* convert offset to be absolute from beginning of the file */ 223 /* convert offset to be absolute from beginning of the file */
224 npos = pc->file_size - npos; 224 npos = pc->file_size - npos;
225 } 225 }
226 if ( (pc->shm_off <= npos) && 226 if ( (pc->shm_off <= npos) &&
227 ((pc->shm_off + pc->shm_ready_bytes > npos) || 227 ((pc->shm_off + pc->shm_ready_bytes > npos) ||
228 (pc->file_size == pc->shm_off)) ) 228 (pc->file_size == pc->shm_off)) )
229 { 229 {
230 pc->read_position = npos; 230 pc->read_position = npos;
231 return (int64_t) npos; 231 return (int64_t) npos;
232 } 232 }
233 /* oops, serious missunderstanding, we asked to seek 233 /* oops, serious missunderstanding, we asked to seek
234 and then were notified about a different position!? */ 234 and then were notified about a different position!? */
235 LOG ("Plugin `%s' got invalid MESSAGE_UPDATED_SHM in response to my %d-seek (%llu not in %llu-%llu)\n", 235 LOG (
236 pc->plugin->short_libname, 236 "Plugin `%s' got invalid MESSAGE_UPDATED_SHM in response to my %d-seek (%llu not in %llu-%llu)\n",
237 (int) wval, 237 pc->plugin->short_libname,
238 (unsigned long long) npos, 238 (int) wval,
239 (unsigned long long) pc->shm_off, 239 (unsigned long long) npos,
240 (unsigned long long) pc->shm_off + pc->shm_ready_bytes); 240 (unsigned long long) pc->shm_off,
241 (unsigned long long) pc->shm_off + pc->shm_ready_bytes);
241 return -1; 242 return -1;
242} 243}
243 244
@@ -252,7 +253,7 @@ plugin_env_seek (void *cls,
252 */ 253 */
253static ssize_t 254static ssize_t
254plugin_env_read (void *cls, 255plugin_env_read (void *cls,
255 void **data, 256 void **data,
256 size_t count) 257 size_t count)
257{ 258{
258 struct ProcessingContext *pc = cls; 259 struct ProcessingContext *pc = cls;
@@ -266,10 +267,10 @@ plugin_env_read (void *cls,
266 (pc->read_position < pc->file_size)) || 267 (pc->read_position < pc->file_size)) ||
267 (pc->read_position < pc->shm_off) ) && 268 (pc->read_position < pc->shm_off) ) &&
268 (-1 == plugin_env_seek (pc, pc->read_position, SEEK_SET) ) ) 269 (-1 == plugin_env_seek (pc, pc->read_position, SEEK_SET) ) )
269 { 270 {
270 LOG ("Failed to seek to satisfy read\n"); 271 LOG ("Failed to seek to satisfy read\n");
271 return -1; 272 return -1;
272 } 273 }
273 if (pc->read_position + count > pc->shm_off + pc->shm_ready_bytes) 274 if (pc->read_position + count > pc->shm_off + pc->shm_ready_bytes)
274 count = pc->shm_off + pc->shm_ready_bytes - pc->read_position; 275 count = pc->shm_off + pc->shm_ready_bytes - pc->read_position;
275 dp = pc->shm; 276 dp = pc->shm;
@@ -313,12 +314,12 @@ plugin_env_get_size (void *cls)
313 */ 314 */
314static int 315static int
315plugin_env_send_proc (void *cls, 316plugin_env_send_proc (void *cls,
316 const char *plugin_name, 317 const char *plugin_name,
317 enum EXTRACTOR_MetaType type, 318 enum EXTRACTOR_MetaType type,
318 enum EXTRACTOR_MetaFormat format, 319 enum EXTRACTOR_MetaFormat format,
319 const char *data_mime_type, 320 const char *data_mime_type,
320 const char *data, 321 const char *data,
321 size_t data_len) 322 size_t data_len)
322{ 323{
323 struct ProcessingContext *pc = cls; 324 struct ProcessingContext *pc = cls;
324 struct MetaMessage mm; 325 struct MetaMessage mm;
@@ -340,32 +341,32 @@ plugin_env_send_proc (void *cls,
340 mm.mime_length = (uint16_t) mime_len; 341 mm.mime_length = (uint16_t) mime_len;
341 mm.value_size = (uint32_t) data_len; 342 mm.value_size = (uint32_t) data_len;
342 if ( (sizeof (mm) != 343 if ( (sizeof (mm) !=
343 EXTRACTOR_write_all_ (pc->out, 344 EXTRACTOR_write_all_ (pc->out,
344 &mm, sizeof (mm))) || 345 &mm, sizeof (mm))) ||
345 (mime_len != 346 (mime_len !=
346 EXTRACTOR_write_all_ (pc->out, 347 EXTRACTOR_write_all_ (pc->out,
347 data_mime_type, mime_len)) || 348 data_mime_type, mime_len)) ||
348 (data_len != 349 (data_len !=
349 EXTRACTOR_write_all_ (pc->out, 350 EXTRACTOR_write_all_ (pc->out,
350 data, data_len)) ) 351 data, data_len)) )
351 { 352 {
352 LOG ("Failed to send meta message\n"); 353 LOG ("Failed to send meta message\n");
353 return 1; 354 return 1;
354 } 355 }
355 if (-1 == 356 if (-1 ==
356 EXTRACTOR_read_all_ (pc->in, 357 EXTRACTOR_read_all_ (pc->in,
357 &reply, sizeof (reply))) 358 &reply, sizeof (reply)))
358 { 359 {
359 LOG ("Failed to read response to meta message\n"); 360 LOG ("Failed to read response to meta message\n");
360 return 1; 361 return 1;
361 } 362 }
362 if (MESSAGE_DISCARD_STATE == reply) 363 if (MESSAGE_DISCARD_STATE == reply)
363 return 1; 364 return 1;
364 if (MESSAGE_CONTINUE_EXTRACTING != reply) 365 if (MESSAGE_CONTINUE_EXTRACTING != reply)
365 { 366 {
366 LOG ("Received unexpected reply to meta data: %d\n", reply); 367 LOG ("Received unexpected reply to meta data: %d\n", reply);
367 return 1; 368 return 1;
368 } 369 }
369 return 0; 370 return 0;
370} 371}
371 372
@@ -382,34 +383,34 @@ handle_init_message (struct ProcessingContext *pc)
382 struct InitMessage init; 383 struct InitMessage init;
383 384
384 if (NULL != pc->shm) 385 if (NULL != pc->shm)
385 { 386 {
386 LOG ("Cannot handle 'init' message, have already been initialized\n"); 387 LOG ("Cannot handle 'init' message, have already been initialized\n");
387 return -1; 388 return -1;
388 } 389 }
389 if (sizeof (struct InitMessage) - 1 390 if (sizeof (struct InitMessage) - 1
390 != EXTRACTOR_read_all_ (pc->in, 391 != EXTRACTOR_read_all_ (pc->in,
391 &init.reserved, 392 &init.reserved,
392 sizeof (struct InitMessage) - 1)) 393 sizeof (struct InitMessage) - 1))
393 { 394 {
394 LOG ("Failed to read 'init' message\n"); 395 LOG ("Failed to read 'init' message\n");
395 return -1; 396 return -1;
396 } 397 }
397 if (init.shm_name_length > MAX_SHM_NAME) 398 if (init.shm_name_length > MAX_SHM_NAME)
398 { 399 {
399 LOG ("Invalid 'init' message\n"); 400 LOG ("Invalid 'init' message\n");
400 return -1; 401 return -1;
401 } 402 }
402 { 403 {
403 char shm_name[init.shm_name_length + 1]; 404 char shm_name[init.shm_name_length + 1];
404 405
405 if (init.shm_name_length 406 if (init.shm_name_length
406 != EXTRACTOR_read_all_ (pc->in, 407 != EXTRACTOR_read_all_ (pc->in,
407 shm_name, 408 shm_name,
408 init.shm_name_length)) 409 init.shm_name_length))
409 { 410 {
410 LOG ("Failed to read 'init' message\n"); 411 LOG ("Failed to read 'init' message\n");
411 return -1; 412 return -1;
412 } 413 }
413 shm_name[init.shm_name_length] = '\0'; 414 shm_name[init.shm_name_length] = '\0';
414 415
415 pc->shm_map_size = init.shm_map_size; 416 pc->shm_map_size = init.shm_map_size;
@@ -427,20 +428,20 @@ handle_init_message (struct ProcessingContext *pc)
427#else 428#else
428 pc->shm_id = shm_open (shm_name, O_RDONLY, 0); 429 pc->shm_id = shm_open (shm_name, O_RDONLY, 0);
429 if (-1 == pc->shm_id) 430 if (-1 == pc->shm_id)
430 { 431 {
431 LOG_STRERROR_FILE ("open", shm_name); 432 LOG_STRERROR_FILE ("open", shm_name);
432 return -1; 433 return -1;
433 } 434 }
434 pc->shm = mmap (NULL, 435 pc->shm = mmap (NULL,
435 pc->shm_map_size, 436 pc->shm_map_size,
436 PROT_READ, 437 PROT_READ,
437 MAP_SHARED, 438 MAP_SHARED,
438 pc->shm_id, 0); 439 pc->shm_id, 0);
439 if ( ((void*) -1) == pc->shm) 440 if ( ((void*) -1) == pc->shm)
440 { 441 {
441 LOG_STRERROR_FILE ("mmap", shm_name); 442 LOG_STRERROR_FILE ("mmap", shm_name);
442 return -1; 443 return -1;
443 } 444 }
444#endif 445#endif
445 } 446 }
446 return 0; 447 return 0;
@@ -462,12 +463,12 @@ handle_start_message (struct ProcessingContext *pc)
462 463
463 if (sizeof (struct StartMessage) - 1 464 if (sizeof (struct StartMessage) - 1
464 != EXTRACTOR_read_all_ (pc->in, 465 != EXTRACTOR_read_all_ (pc->in,
465 &start.reserved, 466 &start.reserved,
466 sizeof (struct StartMessage) - 1)) 467 sizeof (struct StartMessage) - 1))
467 { 468 {
468 LOG ("Failed to read 'start' message\n"); 469 LOG ("Failed to read 'start' message\n");
469 return -1; 470 return -1;
470 } 471 }
471 pc->shm_ready_bytes = start.shm_ready_bytes; 472 pc->shm_ready_bytes = start.shm_ready_bytes;
472 pc->file_size = start.file_size; 473 pc->file_size = start.file_size;
473 pc->read_position = 0; 474 pc->read_position = 0;
@@ -481,22 +482,22 @@ handle_start_message (struct ProcessingContext *pc)
481 pc->plugin->extract_method (&ec); 482 pc->plugin->extract_method (&ec);
482 done = MESSAGE_DONE; 483 done = MESSAGE_DONE;
483 if (-1 == EXTRACTOR_write_all_ (pc->out, &done, sizeof (done))) 484 if (-1 == EXTRACTOR_write_all_ (pc->out, &done, sizeof (done)))
484 { 485 {
485 LOG ("Failed to write 'done' message\n"); 486 LOG ("Failed to write 'done' message\n");
486 return -1; 487 return -1;
487 } 488 }
488 if ( (NULL != pc->plugin->specials) && 489 if ( (NULL != pc->plugin->specials) &&
489 (NULL != strstr (pc->plugin->specials, "force-kill")) ) 490 (NULL != strstr (pc->plugin->specials, "force-kill")) )
490 { 491 {
491 /* we're required to die after each file since this 492 /* we're required to die after each file since this
492 plugin only supports a single file at a time */ 493 plugin only supports a single file at a time */
493#if !WINDOWS 494#if ! WINDOWS
494 fsync (pc->out); 495 fsync (pc->out);
495#else 496#else
496 _commit (pc->out); 497 _commit (pc->out);
497#endif 498#endif
498 _exit (0); 499 _exit (0);
499 } 500 }
500 return 0; 501 return 0;
501} 502}
502 503
@@ -511,43 +512,43 @@ static void
511process_requests (struct ProcessingContext *pc) 512process_requests (struct ProcessingContext *pc)
512{ 513{
513 while (1) 514 while (1)
515 {
516 unsigned char code;
517
518 if (1 != EXTRACTOR_read_all_ (pc->in, &code, 1))
514 { 519 {
515 unsigned char code; 520 LOG ("Failed to read next request\n");
516 521 break;
517 if (1 != EXTRACTOR_read_all_ (pc->in, &code, 1))
518 {
519 LOG ("Failed to read next request\n");
520 break;
521 }
522 switch (code)
523 {
524 case MESSAGE_INIT_STATE:
525 if (0 != handle_init_message (pc))
526 {
527 LOG ("Failure to handle INIT\n");
528 return;
529 }
530 break;
531 case MESSAGE_EXTRACT_START:
532 if (0 != handle_start_message (pc))
533 {
534 LOG ("Failure to handle START\n");
535 return;
536 }
537 break;
538 case MESSAGE_UPDATED_SHM:
539 LOG ("Illegal message\n");
540 /* not allowed here, we're not waiting for SHM to move! */
541 return;
542 case MESSAGE_DISCARD_STATE:
543 /* odd, we're already in the start state... */
544 continue;
545 default:
546 LOG ("Received invalid messag %d\n", (int) code);
547 /* error, unexpected message */
548 return;
549 }
550 } 522 }
523 switch (code)
524 {
525 case MESSAGE_INIT_STATE:
526 if (0 != handle_init_message (pc))
527 {
528 LOG ("Failure to handle INIT\n");
529 return;
530 }
531 break;
532 case MESSAGE_EXTRACT_START:
533 if (0 != handle_start_message (pc))
534 {
535 LOG ("Failure to handle START\n");
536 return;
537 }
538 break;
539 case MESSAGE_UPDATED_SHM:
540 LOG ("Illegal message\n");
541 /* not allowed here, we're not waiting for SHM to move! */
542 return;
543 case MESSAGE_DISCARD_STATE:
544 /* odd, we're already in the start state... */
545 continue;
546 default:
547 LOG ("Received invalid messag %d\n", (int) code);
548 /* error, unexpected message */
549 return;
550 }
551 }
551} 552}
552 553
553 554
@@ -560,7 +561,7 @@ process_requests (struct ProcessingContext *pc)
560 */ 561 */
561static void 562static void
562open_dev_null (int target_fd, 563open_dev_null (int target_fd,
563 int flags) 564 int flags)
564{ 565{
565 int fd; 566 int fd;
566 567
@@ -570,10 +571,10 @@ open_dev_null (int target_fd,
570 fd = open ("\\\\?\\NUL", flags); 571 fd = open ("\\\\?\\NUL", flags);
571#endif 572#endif
572 if (-1 == fd) 573 if (-1 == fd)
573 { 574 {
574 LOG_STRERROR_FILE ("open", "/dev/null"); 575 LOG_STRERROR_FILE ("open", "/dev/null");
575 return; /* good luck */ 576 return; /* good luck */
576 } 577 }
577 if (fd == target_fd) 578 if (fd == target_fd)
578 return; /* already done */ 579 return; /* already done */
579 if (-1 == dup2 (fd, target_fd)) 580 if (-1 == dup2 (fd, target_fd))
@@ -598,32 +599,32 @@ open_dev_null (int target_fd,
598 */ 599 */
599void 600void
600EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin, 601EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin,
601 int in, int out) 602 int in, int out)
602{ 603{
603 struct ProcessingContext pc; 604 struct ProcessingContext pc;
604 605
605 if (0 != EXTRACTOR_plugin_load_ (plugin)) 606 if (0 != EXTRACTOR_plugin_load_ (plugin))
606 { 607 {
607#if DEBUG 608#if DEBUG
608 fprintf (stderr, "Plugin `%s' failed to load!\n", 609 fprintf (stderr, "Plugin `%s' failed to load!\n",
609 plugin->short_libname); 610 plugin->short_libname);
610#endif 611#endif
611 return; 612 return;
612 } 613 }
613 if ( (NULL != plugin->specials) && 614 if ( (NULL != plugin->specials) &&
614 (NULL != strstr (plugin->specials, "close-stderr"))) 615 (NULL != strstr (plugin->specials, "close-stderr")))
615 { 616 {
616 if (0 != close (2)) 617 if (0 != close (2))
617 LOG_STRERROR ("close"); 618 LOG_STRERROR ("close");
618 open_dev_null (2, O_WRONLY); 619 open_dev_null (2, O_WRONLY);
619 } 620 }
620 if ( (NULL != plugin->specials) && 621 if ( (NULL != plugin->specials) &&
621 (NULL != strstr (plugin->specials, "close-stdout"))) 622 (NULL != strstr (plugin->specials, "close-stdout")))
622 { 623 {
623 if (0 != close (1)) 624 if (0 != close (1))
624 LOG_STRERROR ("close"); 625 LOG_STRERROR ("close");
625 open_dev_null (1, O_WRONLY); 626 open_dev_null (1, O_WRONLY);
626 } 627 }
627 pc.plugin = plugin; 628 pc.plugin = plugin;
628 pc.in = in; 629 pc.in = in;
629 pc.out = out; 630 pc.out = out;
@@ -643,10 +644,10 @@ EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin,
643 (((void*) 1) != pc.shm) ) 644 (((void*) 1) != pc.shm) )
644 munmap (pc.shm, pc.shm_map_size); 645 munmap (pc.shm, pc.shm_map_size);
645 if (-1 != pc.shm_id) 646 if (-1 != pc.shm_id)
646 { 647 {
647 if (0 != close (pc.shm_id)) 648 if (0 != close (pc.shm_id))
648 LOG_STRERROR ("close"); 649 LOG_STRERROR ("close");
649 } 650 }
650#endif 651#endif
651} 652}
652 653
@@ -668,43 +669,43 @@ read_plugin_data (int fd)
668 669
669 // FIXME: check for errors from 'EXTRACTOR_read_all_'! 670 // FIXME: check for errors from 'EXTRACTOR_read_all_'!
670 if (NULL == (ret = malloc (sizeof (struct EXTRACTOR_PluginList)))) 671 if (NULL == (ret = malloc (sizeof (struct EXTRACTOR_PluginList))))
671 { 672 {
672 LOG_STRERROR ("malloc"); 673 LOG_STRERROR ("malloc");
673 return NULL; 674 return NULL;
674 } 675 }
675 memset (ret, 0, sizeof (struct EXTRACTOR_PluginList)); 676 memset (ret, 0, sizeof (struct EXTRACTOR_PluginList));
676 /*GetSystemInfo (&si); 677 /*GetSystemInfo (&si);
677 ret->allocation_granularity = si.dwAllocationGranularity;*/ 678 ret->allocation_granularity = si.dwAllocationGranularity;*/
678 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); 679 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t));
679 if (NULL == (ret->libname = malloc (i))) 680 if (NULL == (ret->libname = malloc (i)))
680 { 681 {
681 free (ret); 682 free (ret);
682 return NULL; 683 return NULL;
683 } 684 }
684 EXTRACTOR_read_all_ (fd, ret->libname, i); 685 EXTRACTOR_read_all_ (fd, ret->libname, i);
685 ret->libname[i - 1] = '\0'; 686 ret->libname[i - 1] = '\0';
686 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); 687 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t));
687 if (NULL == (ret->short_libname = malloc (i))) 688 if (NULL == (ret->short_libname = malloc (i)))
688 { 689 {
689 free (ret->libname); 690 free (ret->libname);
690 free (ret); 691 free (ret);
691 return NULL; 692 return NULL;
692 } 693 }
693 EXTRACTOR_read_all_ (fd, ret->short_libname, i); 694 EXTRACTOR_read_all_ (fd, ret->short_libname, i);
694 ret->short_libname[i - 1] = '\0'; 695 ret->short_libname[i - 1] = '\0';
695 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); 696 EXTRACTOR_read_all_ (fd, &i, sizeof (size_t));
696 if (0 == i) 697 if (0 == i)
697 { 698 {
698 ret->plugin_options = NULL; 699 ret->plugin_options = NULL;
699 return ret; 700 return ret;
700 } 701 }
701 if (NULL == (ret->plugin_options = malloc (i))) 702 if (NULL == (ret->plugin_options = malloc (i)))
702 { 703 {
703 free (ret->short_libname); 704 free (ret->short_libname);
704 free (ret->libname); 705 free (ret->libname);
705 free (ret); 706 free (ret);
706 return NULL; 707 return NULL;
707 } 708 }
708 EXTRACTOR_read_all_ (fd, ret->plugin_options, i); 709 EXTRACTOR_read_all_ (fd, ret->plugin_options, i);
709 ret->plugin_options[i - 1] = '\0'; 710 ret->plugin_options[i - 1] = '\0';
710 return ret; 711 return ret;
@@ -716,9 +717,9 @@ read_plugin_data (int fd)
716 */ 717 */
717void CALLBACK 718void CALLBACK
718RundllEntryPoint (HWND hwnd, 719RundllEntryPoint (HWND hwnd,
719 HINSTANCE hinst, 720 HINSTANCE hinst,
720 LPSTR lpszCmdLine, 721 LPSTR lpszCmdLine,
721 int nCmdShow) 722 int nCmdShow)
722{ 723{
723 struct EXTRACTOR_PluginList *plugin; 724 struct EXTRACTOR_PluginList *plugin;
724 intptr_t in_h; 725 intptr_t in_h;
@@ -732,11 +733,11 @@ RundllEntryPoint (HWND hwnd,
732 setmode (in, _O_BINARY); 733 setmode (in, _O_BINARY);
733 setmode (out, _O_BINARY); 734 setmode (out, _O_BINARY);
734 if (NULL == (plugin = read_plugin_data (in))) 735 if (NULL == (plugin = read_plugin_data (in)))
735 { 736 {
736 close (in); 737 close (in);
737 close (out); 738 close (out);
738 return; 739 return;
739 } 740 }
740 EXTRACTOR_plugin_main_ (plugin, in, out); 741 EXTRACTOR_plugin_main_ (plugin, in, out);
741 close (in); 742 close (in);
742 close (out); 743 close (out);
@@ -745,8 +746,7 @@ RundllEntryPoint (HWND hwnd,
745 * called by the OS) or call FreeLibrary() on it directly or 746 * called by the OS) or call FreeLibrary() on it directly or
746 * indirectly. 747 * indirectly.
747 * By terminating here we alleviate that problem. 748 * By terminating here we alleviate that problem.
748 */ 749 */TerminateProcess (GetCurrentProcess (), 0);
749 TerminateProcess (GetCurrentProcess (), 0);
750} 750}
751 751
752 752
@@ -755,9 +755,9 @@ RundllEntryPoint (HWND hwnd,
755 */ 755 */
756void CALLBACK 756void CALLBACK
757RundllEntryPointA (HWND hwnd, 757RundllEntryPointA (HWND hwnd,
758 HINSTANCE hinst, 758 HINSTANCE hinst,
759 LPSTR lpszCmdLine, 759 LPSTR lpszCmdLine,
760 int nCmdShow) 760 int nCmdShow)
761{ 761{
762 return RundllEntryPoint (hwnd, hinst, lpszCmdLine, nCmdShow); 762 return RundllEntryPoint (hwnd, hinst, lpszCmdLine, nCmdShow);
763} 763}
diff --git a/src/main/extractor_plugin_main.h b/src/main/extractor_plugin_main.h
index 1b33c8c..a683768 100644
--- a/src/main/extractor_plugin_main.h
+++ b/src/main/extractor_plugin_main.h
@@ -37,7 +37,7 @@
37 * @param out stream to write to 37 * @param out stream to write to
38 */ 38 */
39void 39void
40EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin, 40 EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin,
41 int in, int out); 41 int in, int out);
42 42
43#endif 43#endif
diff --git a/src/main/extractor_plugins.c b/src/main/extractor_plugins.c
index 0fa10d6..1ab777b 100644
--- a/src/main/extractor_plugins.c
+++ b/src/main/extractor_plugins.c
@@ -39,9 +39,9 @@
39 */ 39 */
40static void * 40static void *
41get_symbol_with_prefix (void *lib_handle, 41get_symbol_with_prefix (void *lib_handle,
42 const char *template, 42 const char *template,
43 const char *prefix, 43 const char *prefix,
44 const char **options) 44 const char **options)
45{ 45{
46 char *name; 46 char *name;
47 void *symbol; 47 void *symbol;
@@ -56,55 +56,55 @@ get_symbol_with_prefix (void *lib_handle,
56 return NULL; 56 return NULL;
57 sym_name++; 57 sym_name++;
58 if (NULL == (sym = strdup (sym_name))) 58 if (NULL == (sym = strdup (sym_name)))
59 { 59 {
60 LOG_STRERROR ("strdup"); 60 LOG_STRERROR ("strdup");
61 return NULL; 61 return NULL;
62 } 62 }
63 if (NULL != (dot = strchr (sym, '.'))) 63 if (NULL != (dot = strchr (sym, '.')))
64 *dot = '\0'; 64 *dot = '\0';
65 if (NULL == (name = malloc(strlen(sym) + strlen(template) + 1))) 65 if (NULL == (name = malloc (strlen (sym) + strlen (template) + 1)))
66 { 66 {
67 free (sym); 67 free (sym);
68 return NULL; 68 return NULL;
69 } 69 }
70 sprintf(name, 70 sprintf (name,
71 template, 71 template,
72 sym); 72 sym);
73 /* try without '_' first */ 73 /* try without '_' first */
74 symbol = lt_dlsym (lib_handle, name + 1); 74 symbol = lt_dlsym (lib_handle, name + 1);
75 if (NULL == symbol) 75 if (NULL == symbol)
76 {
77 /* now try with the '_' */
78 char *first_error = strdup (lt_dlerror ());
79 symbol = lt_dlsym (lib_handle, name);
80 if (NULL == symbol)
76 { 81 {
77 /* now try with the '_' */ 82 LOG ("Resolving symbol `%s' failed, "
78 char *first_error = strdup (lt_dlerror ()); 83 "so I tried `%s', but that failed also. Errors are: "
79 symbol = lt_dlsym (lib_handle, name); 84 "`%s' and `%s'.\n",
80 if (NULL == symbol) 85 name + 1,
81 { 86 name,
82 LOG ("Resolving symbol `%s' failed, " 87 first_error == NULL ? "out of memory" : first_error,
83 "so I tried `%s', but that failed also. Errors are: " 88 lt_dlerror ());
84 "`%s' and `%s'.\n",
85 name+1,
86 name,
87 first_error == NULL ? "out of memory" : first_error,
88 lt_dlerror ());
89 }
90 if (NULL != first_error)
91 free (first_error);
92 } 89 }
90 if (NULL != first_error)
91 free (first_error);
92 }
93 93
94 if ( (NULL != symbol) && 94 if ( (NULL != symbol) &&
95 (NULL != options) ) 95 (NULL != options) )
96 { 96 {
97 /* get special options */ 97 /* get special options */
98 sprintf (name, 98 sprintf (name,
99 "_EXTRACTOR_%s_options", 99 "_EXTRACTOR_%s_options",
100 sym); 100 sym);
101 /* try without '_' first */ 101 /* try without '_' first */
102 opt_fun = lt_dlsym (lib_handle, name + 1); 102 opt_fun = lt_dlsym (lib_handle, name + 1);
103 if (NULL == opt_fun) 103 if (NULL == opt_fun)
104 opt_fun = lt_dlsym (lib_handle, name); 104 opt_fun = lt_dlsym (lib_handle, name);
105 if (NULL != opt_fun) 105 if (NULL != opt_fun)
106 *options = opt_fun (); 106 *options = opt_fun ();
107 } 107 }
108 free (sym); 108 free (sym);
109 free (name); 109 free (name);
110 return symbol; 110 return symbol;
@@ -131,12 +131,12 @@ EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
131 if (NULL == plugin->libname) 131 if (NULL == plugin->libname)
132 plugin->libname = EXTRACTOR_find_plugin_ (plugin->short_libname); 132 plugin->libname = EXTRACTOR_find_plugin_ (plugin->short_libname);
133 if (NULL == plugin->libname) 133 if (NULL == plugin->libname)
134 { 134 {
135 LOG ("Failed to find plugin `%s'\n", 135 LOG ("Failed to find plugin `%s'\n",
136 plugin->short_libname); 136 plugin->short_libname);
137 plugin->flags = EXTRACTOR_OPTION_DISABLED; 137 plugin->flags = EXTRACTOR_OPTION_DISABLED;
138 return -1; 138 return -1;
139 } 139 }
140 lt_dladvise_init (&advise); 140 lt_dladvise_init (&advise);
141 lt_dladvise_ext (&advise); 141 lt_dladvise_ext (&advise);
142 lt_dladvise_local (&advise); 142 lt_dladvise_local (&advise);
@@ -144,51 +144,51 @@ EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
144 wlibname[0] = L'\0'; 144 wlibname[0] = L'\0';
145 llibname[0] = '\0'; 145 llibname[0] = '\0';
146 if ( (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1, 146 if ( (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1,
147 wlibname, sizeof (wlibname)) <= 0) || 147 wlibname, sizeof (wlibname)) <= 0) ||
148 (WideCharToMultiByte (CP_ACP, 0, wlibname, -1, 148 (WideCharToMultiByte (CP_ACP, 0, wlibname, -1,
149 llibname, sizeof (llibname), NULL, NULL) < 0) ) 149 llibname, sizeof (llibname), NULL, NULL) < 0) )
150 { 150 {
151 LOG ("Loading `%s' plugin failed: %s\n", 151 LOG ("Loading `%s' plugin failed: %s\n",
152 plugin->short_libname, 152 plugin->short_libname,
153 "can't convert plugin name to local encoding"); 153 "can't convert plugin name to local encoding");
154 free (plugin->libname); 154 free (plugin->libname);
155 plugin->libname = NULL; 155 plugin->libname = NULL;
156 plugin->flags = EXTRACTOR_OPTION_DISABLED; 156 plugin->flags = EXTRACTOR_OPTION_DISABLED;
157 return -1; 157 return -1;
158 } 158 }
159 plugin->libraryHandle = lt_dlopenadvise (llibname, 159 plugin->libraryHandle = lt_dlopenadvise (llibname,
160 advise); 160 advise);
161#else 161#else
162 plugin->libraryHandle = lt_dlopenadvise (plugin->libname, 162 plugin->libraryHandle = lt_dlopenadvise (plugin->libname,
163 advise); 163 advise);
164#endif 164#endif
165 lt_dladvise_destroy (&advise); 165 lt_dladvise_destroy (&advise);
166 if (NULL == plugin->libraryHandle) 166 if (NULL == plugin->libraryHandle)
167 { 167 {
168 LOG ("Loading `%s' plugin failed (using name `%s'): %s\n", 168 LOG ("Loading `%s' plugin failed (using name `%s'): %s\n",
169 plugin->short_libname, 169 plugin->short_libname,
170 plugin->libname, 170 plugin->libname,
171 lt_dlerror ()); 171 lt_dlerror ());
172 free (plugin->libname); 172 free (plugin->libname);
173 plugin->libname = NULL; 173 plugin->libname = NULL;
174 plugin->flags = EXTRACTOR_OPTION_DISABLED; 174 plugin->flags = EXTRACTOR_OPTION_DISABLED;
175 return -1; 175 return -1;
176 } 176 }
177 plugin->extract_method = get_symbol_with_prefix (plugin->libraryHandle, 177 plugin->extract_method = get_symbol_with_prefix (plugin->libraryHandle,
178 "_EXTRACTOR_%s_extract_method", 178 "_EXTRACTOR_%s_extract_method",
179 plugin->libname, 179 plugin->libname,
180 &plugin->specials); 180 &plugin->specials);
181 if (NULL == plugin->extract_method) 181 if (NULL == plugin->extract_method)
182 { 182 {
183 LOG ("Resolving `extract' method of plugin `%s' failed: %s\n", 183 LOG ("Resolving `extract' method of plugin `%s' failed: %s\n",
184 plugin->short_libname, 184 plugin->short_libname,
185 lt_dlerror ()); 185 lt_dlerror ());
186 lt_dlclose (plugin->libraryHandle); 186 lt_dlclose (plugin->libraryHandle);
187 free (plugin->libname); 187 free (plugin->libname);
188 plugin->libname = NULL; 188 plugin->libname = NULL;
189 plugin->flags = EXTRACTOR_OPTION_DISABLED; 189 plugin->flags = EXTRACTOR_OPTION_DISABLED;
190 return -1; 190 return -1;
191 } 191 }
192 return 0; 192 return 0;
193} 193}
194 194
@@ -204,9 +204,9 @@ EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
204 */ 204 */
205struct EXTRACTOR_PluginList * 205struct EXTRACTOR_PluginList *
206EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev, 206EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
207 const char *library, 207 const char *library,
208 const char *options, 208 const char *options,
209 enum EXTRACTOR_Options flags) 209 enum EXTRACTOR_Options flags)
210{ 210{
211 struct EXTRACTOR_PluginList *plugin; 211 struct EXTRACTOR_PluginList *plugin;
212 struct EXTRACTOR_PluginList *pos; 212 struct EXTRACTOR_PluginList *pos;
@@ -214,22 +214,23 @@ EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
214 214
215 for (pos = prev; NULL != pos; pos = pos->next) 215 for (pos = prev; NULL != pos; pos = pos->next)
216 if (0 == strcmp (pos->short_libname, library)) 216 if (0 == strcmp (pos->short_libname, library))
217 return prev; /* no change, library already loaded */
218 if (NULL == (libname = EXTRACTOR_find_plugin_ (library)))
219 {
220 LOG ("Could not load plugin `%s'\n",
221 library);
222 return prev; 217 return prev;
223 } 218 /* no change, library already loaded */
219 if (NULL == (libname = EXTRACTOR_find_plugin_ (library)))
220 {
221 LOG ("Could not load plugin `%s'\n",
222 library);
223 return prev;
224 }
224 if (NULL == (plugin = malloc (sizeof (struct EXTRACTOR_PluginList)))) 225 if (NULL == (plugin = malloc (sizeof (struct EXTRACTOR_PluginList))))
225 return prev; 226 return prev;
226 memset (plugin, 0, sizeof (struct EXTRACTOR_PluginList)); 227 memset (plugin, 0, sizeof (struct EXTRACTOR_PluginList));
227 plugin->next = prev; 228 plugin->next = prev;
228 if (NULL == (plugin->short_libname = strdup (library))) 229 if (NULL == (plugin->short_libname = strdup (library)))
229 { 230 {
230 free (plugin); 231 free (plugin);
231 return NULL; 232 return NULL;
232 } 233 }
233 plugin->libname = libname; 234 plugin->libname = libname;
234 plugin->flags = flags; 235 plugin->flags = flags;
235 if (NULL != options) 236 if (NULL != options)
@@ -258,8 +259,8 @@ EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
258 */ 259 */
259struct EXTRACTOR_PluginList * 260struct EXTRACTOR_PluginList *
260EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev, 261EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
261 const char *config, 262 const char *config,
262 enum EXTRACTOR_Options flags) 263 enum EXTRACTOR_Options flags)
263{ 264{
264 char *cpy; 265 char *cpy;
265 size_t pos; 266 size_t pos;
@@ -276,55 +277,55 @@ EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
276 last = 0; 277 last = 0;
277 lastconf = 0; 278 lastconf = 0;
278 while (pos < len) 279 while (pos < len)
280 {
281 while ( (':' != cpy[pos]) &&
282 ('\0' != cpy[pos]) &&
283 ('(' != cpy[pos]) )
284 pos++;
285 switch (cpy[pos])
279 { 286 {
280 while ( (':' != cpy[pos]) && 287 case '(':
281 ('\0' != cpy[pos]) && 288 cpy[pos++] = '\0'; /* replace '(' by termination */
282 ('(' != cpy[pos]) ) 289 lastconf = pos; /* start config from here, after (. */
283 pos++; 290 while ( ('\0' != cpy[pos]) &&
284 switch (cpy[pos]) 291 (')' != cpy[pos]))
285 { 292 pos++; /* config until ) or EOS. */
286 case '(': 293 if (')' == cpy[pos])
287 cpy[pos++] = '\0'; /* replace '(' by termination */ 294 {
288 lastconf = pos; /* start config from here, after (. */ 295 cpy[pos++] = '\0'; /* write end of config here. */
289 while ( ('\0' != cpy[pos]) && 296 while ( (':' != cpy[pos]) &&
290 (')' != cpy[pos])) 297 ('\0' != cpy[pos]) )
291 pos++; /* config until ) or EOS. */ 298 pos++; /* forward until real end of string found. */
292 if (')' == cpy[pos]) 299 cpy[pos++] = '\0';
293 { 300 }
294 cpy[pos++] = '\0'; /* write end of config here. */
295 while ( (':' != cpy[pos]) &&
296 ('\0' != cpy[pos]) )
297 pos++; /* forward until real end of string found. */
298 cpy[pos++] = '\0';
299 }
300 else
301 {
302 cpy[pos++] = '\0'; /* end of string. */
303 }
304 break;
305 case ':':
306 case '\0':
307 lastconf = -1; /* NULL config when no (). */
308 cpy[pos++] = '\0'; /* replace ':' by termination */
309 break;
310 default:
311 ABORT ();
312 }
313 if ('-' == cpy[last])
314 {
315 last++;
316 prev = EXTRACTOR_plugin_remove (prev,
317 &cpy[last]);
318 }
319 else 301 else
320 { 302 {
321 prev = EXTRACTOR_plugin_add (prev, 303 cpy[pos++] = '\0'; /* end of string. */
322 &cpy[last], 304 }
323 (-1 != lastconf) ? &cpy[lastconf] : NULL, 305 break;
324 flags); 306 case ':':
325 } 307 case '\0':
326 last = pos; 308 lastconf = -1; /* NULL config when no (). */
309 cpy[pos++] = '\0'; /* replace ':' by termination */
310 break;
311 default:
312 ABORT ();
327 } 313 }
314 if ('-' == cpy[last])
315 {
316 last++;
317 prev = EXTRACTOR_plugin_remove (prev,
318 &cpy[last]);
319 }
320 else
321 {
322 prev = EXTRACTOR_plugin_add (prev,
323 &cpy[last],
324 (-1 != lastconf) ? &cpy[lastconf] : NULL,
325 flags);
326 }
327 last = pos;
328 }
328 free (cpy); 329 free (cpy);
329 return prev; 330 return prev;
330} 331}
@@ -339,7 +340,7 @@ EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
339 */ 340 */
340struct EXTRACTOR_PluginList * 341struct EXTRACTOR_PluginList *
341EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev, 342EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
342 const char *library) 343 const char *library)
343{ 344{
344 struct EXTRACTOR_PluginList *pos; 345 struct EXTRACTOR_PluginList *pos;
345 struct EXTRACTOR_PluginList *first; 346 struct EXTRACTOR_PluginList *first;
@@ -347,17 +348,17 @@ EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
347 pos = prev; 348 pos = prev;
348 first = prev; 349 first = prev;
349 while ( (NULL != pos) && 350 while ( (NULL != pos) &&
350 (0 != strcmp (pos->short_libname, library)) ) 351 (0 != strcmp (pos->short_libname, library)) )
351 { 352 {
352 prev = pos; 353 prev = pos;
353 pos = pos->next; 354 pos = pos->next;
354 } 355 }
355 if (NULL == pos) 356 if (NULL == pos)
356 { 357 {
357 LOG ("Unloading plugin `%s' failed!\n", 358 LOG ("Unloading plugin `%s' failed!\n",
358 library); 359 library);
359 return first; 360 return first;
360 } 361 }
361 /* found, close library */ 362 /* found, close library */
362 if (first == pos) 363 if (first == pos)
363 first = pos->next; 364 first = pos->next;
@@ -374,7 +375,7 @@ EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
374 free (pos->libname); 375 free (pos->libname);
375 free (pos->plugin_options); 376 free (pos->plugin_options);
376 if (NULL != pos->libraryHandle) 377 if (NULL != pos->libraryHandle)
377 lt_dlclose (pos->libraryHandle); 378 lt_dlclose (pos->libraryHandle);
378 free (pos); 379 free (pos);
379 return first; 380 return first;
380} 381}
diff --git a/src/main/extractor_plugins.h b/src/main/extractor_plugins.h
index 958ad94..8b0f5e6 100644
--- a/src/main/extractor_plugins.h
+++ b/src/main/extractor_plugins.h
@@ -59,7 +59,7 @@ struct EXTRACTOR_PluginList
59 * Short name of the plugin (i.e., 'foo') 59 * Short name of the plugin (i.e., 'foo')
60 */ 60 */
61 char *short_libname; 61 char *short_libname;
62 62
63 /** 63 /**
64 * Pointer to the function used for meta data extraction. 64 * Pointer to the function used for meta data extraction.
65 */ 65 */
diff --git a/src/main/extractor_plugpath.c b/src/main/extractor_plugpath.c
index 461f25e..4374bc5 100644
--- a/src/main/extractor_plugpath.c
+++ b/src/main/extractor_plugpath.c
@@ -41,7 +41,7 @@
41 * @param path a directory path 41 * @param path a directory path
42 */ 42 */
43typedef void (*EXTRACTOR_PathProcessor) (void *cls, 43typedef void (*EXTRACTOR_PathProcessor) (void *cls,
44 const char *path); 44 const char *path);
45 45
46 46
47/** 47/**
@@ -51,7 +51,7 @@ typedef void (*EXTRACTOR_PathProcessor) (void *cls,
51 * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed 51 * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed
52 */ 52 */
53static char * 53static char *
54cut_bin (char * in) 54cut_bin (char *in)
55{ 55{
56 size_t p; 56 size_t p;
57 57
@@ -60,21 +60,21 @@ cut_bin (char * in)
60 p = strlen (in); 60 p = strlen (in);
61 if (p < 4) 61 if (p < 4)
62 return in; 62 return in;
63 if ( ('/' == in[p-1]) || 63 if ( ('/' == in[p - 1]) ||
64 ('\\' == in[p-1]) ) 64 ('\\' == in[p - 1]) )
65 in[--p] = '\0'; 65 in[--p] = '\0';
66 if (0 == strcmp (&in[p-4], 66 if (0 == strcmp (&in[p - 4],
67 "/bin")) 67 "/bin"))
68 { 68 {
69 in[p-4] = '\0'; 69 in[p - 4] = '\0';
70 p -= 4; 70 p -= 4;
71 } 71 }
72 else if (0 == strcmp (&in[p-4], 72 else if (0 == strcmp (&in[p - 4],
73 "\\bin")) 73 "\\bin"))
74 { 74 {
75 in[p-4] = '\0'; 75 in[p - 4] = '\0';
76 p -= 4; 76 p -= 4;
77 } 77 }
78 return in; 78 return in;
79} 79}
80 80
@@ -100,60 +100,62 @@ get_path_from_proc_exe ()
100 FILE *f; 100 FILE *f;
101 101
102 snprintf (fn, 102 snprintf (fn,
103 sizeof (fn), 103 sizeof (fn),
104 "/proc/%u/maps", 104 "/proc/%u/maps",
105 getpid ()); 105 getpid ());
106 if (NULL != (f = FOPEN (fn, "r"))) 106 if (NULL != (f = FOPEN (fn, "r")))
107 {
108 while (NULL != fgets (line, 1024, f))
107 { 109 {
108 while (NULL != fgets (line, 1024, f)) 110 if ( (1 == sscanf (line,
109 { 111 "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s",
110 if ( (1 == sscanf (line, 112 dir)) &&
111 "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s", 113 (NULL != (lestr = strstr (dir,
112 dir)) && 114 "libextractor")) ) )
113 (NULL != (lestr = strstr (dir, 115 {
114 "libextractor")) ) ) 116 lestr[0] = '\0';
115 { 117 fclose (f);
116 lestr[0] = '\0'; 118 return strdup (dir);
117 fclose (f); 119 }
118 return strdup (dir);
119 }
120 }
121 fclose (f);
122 } 120 }
121 fclose (f);
122 }
123 snprintf (fn, 123 snprintf (fn,
124 sizeof (fn), 124 sizeof (fn),
125 "/proc/%u/exe", 125 "/proc/%u/exe",
126 getpid ()); 126 getpid ());
127 if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */ 127 if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */
128 return NULL; 128 return NULL;
129 size = readlink (fn, lnk, 1023); 129 size = readlink (fn, lnk, 1023);
130 if ( (size <= 0) || (size >= 1024) ) 130 if ( (size <= 0) || (size >= 1024) )
131 { 131 {
132 free (lnk); 132 free (lnk);
133 return NULL; 133 return NULL;
134 } 134 }
135 lnk[size] = '\0'; 135 lnk[size] = '\0';
136 while ( ('/' != lnk[size]) && 136 while ( ('/' != lnk[size]) &&
137 (size > 0) ) 137 (size > 0) )
138 size--; 138 size--;
139 if ( (size < 4) || 139 if ( (size < 4) ||
140 ('/' != lnk[size-4]) ) 140 ('/' != lnk[size - 4]) )
141 { 141 {
142 /* not installed in "/bin/" -- binary path probably useless */ 142 /* not installed in "/bin/" -- binary path probably useless */
143 free (lnk); 143 free (lnk);
144 return NULL; 144 return NULL;
145 } 145 }
146 lnk[size] = '\0'; 146 lnk[size] = '\0';
147 lnk = cut_bin (lnk); 147 lnk = cut_bin (lnk);
148 if (NULL == (ret = realloc (lnk, strlen(lnk) + 6))) 148 if (NULL == (ret = realloc (lnk, strlen (lnk) + 6)))
149 { 149 {
150 LOG_STRERROR ("realloc"); 150 LOG_STRERROR ("realloc");
151 free (lnk); 151 free (lnk);
152 return NULL; 152 return NULL;
153 } 153 }
154 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ 154 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
155 return ret; 155 return ret;
156} 156}
157
158
157#endif 159#endif
158 160
159 161
@@ -162,8 +164,8 @@ static HMODULE le_dll = NULL;
162 164
163BOOL WINAPI 165BOOL WINAPI
164DllMain (HINSTANCE hinstDLL, 166DllMain (HINSTANCE hinstDLL,
165 DWORD fdwReason, 167 DWORD fdwReason,
166 LPVOID lpvReserved) 168 LPVOID lpvReserved)
167{ 169{
168 switch (fdwReason) 170 switch (fdwReason)
169 { 171 {
@@ -175,6 +177,7 @@ DllMain (HINSTANCE hinstDLL,
175 return TRUE; 177 return TRUE;
176} 178}
177 179
180
178/** 181/**
179 * Try to determine path with win32-specific function 182 * Try to determine path with win32-specific function
180 */ 183 */
@@ -190,20 +193,22 @@ get_path_from_module_filename ()
190 GetModuleFileName (le_dll, path, 4096); 193 GetModuleFileName (le_dll, path, 4096);
191 idx = path + strlen (path); 194 idx = path + strlen (path);
192 while ( (idx > path) && 195 while ( (idx > path) &&
193 ('\\' != *idx) && 196 ('\\' != *idx) &&
194 ('/' != *idx) ) 197 ('/' != *idx) )
195 idx--; 198 idx--;
196 *idx = '\0'; 199 *idx = '\0';
197 path = cut_bin (path); 200 path = cut_bin (path);
198 if (NULL == (ret = realloc (path, strlen(path) + 6))) 201 if (NULL == (ret = realloc (path, strlen (path) + 6)))
199 { 202 {
200 LOG_STRERROR ("realloc"); 203 LOG_STRERROR ("realloc");
201 free (path); 204 free (path);
202 return NULL; 205 return NULL;
203 } 206 }
204 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ 207 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
205 return ret; 208 return ret;
206} 209}
210
211
207#endif 212#endif
208 213
209 214
@@ -239,8 +244,8 @@ get_path_from_NSGetExecutablePath ()
239 244
240 path = NULL; 245 path = NULL;
241 if (NULL == (func = 246 if (NULL == (func =
242 (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, 247 (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT,
243 "_NSGetExecutablePath"))) 248 "_NSGetExecutablePath")))
244 return NULL; 249 return NULL;
245 path = &zero; 250 path = &zero;
246 len = 0; 251 len = 0;
@@ -249,10 +254,10 @@ get_path_from_NSGetExecutablePath ()
249 if (0 == len) 254 if (0 == len)
250 return NULL; 255 return NULL;
251 if (NULL == (path = malloc (len))) 256 if (NULL == (path = malloc (len)))
252 { 257 {
253 LOG_STRERROR ("malloc"); 258 LOG_STRERROR ("malloc");
254 return NULL; 259 return NULL;
255 } 260 }
256 if (0 != func (path, &len)) 261 if (0 != func (path, &len))
257 { 262 {
258 free (path); 263 free (path);
@@ -267,9 +272,9 @@ get_path_from_NSGetExecutablePath ()
267 path = cut_bin (path); 272 path = cut_bin (path);
268 if (NULL == (ret = realloc (path, strlen (path) + 5))) 273 if (NULL == (ret = realloc (path, strlen (path) + 5)))
269 { 274 {
270 LOG_STRERROR ("realloc"); 275 LOG_STRERROR ("realloc");
271 free (path); 276 free (path);
272 return NULL; 277 return NULL;
273 } 278 }
274 strcat (ret, "/lib/"); 279 strcat (ret, "/lib/");
275 return ret; 280 return ret;
@@ -292,26 +297,28 @@ get_path_from_dyld_image ()
292 297
293 c = _dyld_image_count (); 298 c = _dyld_image_count ();
294 for (i = 0; i < c; i++) 299 for (i = 0; i < c; i++)
300 {
301 if (((void *) _dyld_get_image_header (i)) != (void *) &_mh_dylib_header)
302 continue;
303 path = _dyld_get_image_name (i);
304 if ( (NULL == path) || (0 == strlen (path)) )
305 continue;
306 if (NULL == (p = strdup (path)))
295 { 307 {
296 if (((void *) _dyld_get_image_header (i)) != (void *) &_mh_dylib_header) 308 LOG_STRERROR ("strdup");
297 continue; 309 return NULL;
298 path = _dyld_get_image_name (i);
299 if ( (NULL == path) || (0 == strlen (path)) )
300 continue;
301 if (NULL == (p = strdup (path)))
302 {
303 LOG_STRERROR ("strdup");
304 return NULL;
305 }
306 s = p + strlen (p);
307 while ( (s > p) && ('/' != *s) )
308 s--;
309 s++;
310 *s = '\0';
311 return p;
312 } 310 }
311 s = p + strlen (p);
312 while ( (s > p) && ('/' != *s) )
313 s--;
314 s++;
315 *s = '\0';
316 return p;
317 }
313 return NULL; 318 return NULL;
314} 319}
320
321
315#endif 322#endif
316 323
317 324
@@ -322,7 +329,7 @@ get_path_from_dyld_image ()
322 * @return path to binary, NULL if not found 329 * @return path to binary, NULL if not found
323 */ 330 */
324static char * 331static char *
325get_path_from_PATH() 332get_path_from_PATH ()
326{ 333{
327 struct stat sbuf; 334 struct stat sbuf;
328 char *path; 335 char *path;
@@ -335,61 +342,61 @@ get_path_from_PATH()
335 if (NULL == (p = getenv ("PATH"))) 342 if (NULL == (p = getenv ("PATH")))
336 return NULL; 343 return NULL;
337 if (NULL == (path = strdup (p))) /* because we write on it */ 344 if (NULL == (path = strdup (p))) /* because we write on it */
338 { 345 {
339 LOG_STRERROR ("strdup"); 346 LOG_STRERROR ("strdup");
340 return NULL; 347 return NULL;
341 } 348 }
342 if (NULL == (buf = malloc (strlen (path) + 20))) 349 if (NULL == (buf = malloc (strlen (path) + 20)))
343 { 350 {
344 LOG_STRERROR ("malloc"); 351 LOG_STRERROR ("malloc");
345 free (path); 352 free (path);
346 return NULL; 353 return NULL;
347 } 354 }
348 pos = path; 355 pos = path;
349 while (NULL != (end = strchr(pos, ':'))) 356 while (NULL != (end = strchr (pos, ':')))
350 { 357 {
351 *end = '\0'; 358 *end = '\0';
352 sprintf (buf, "%s/%s", pos, "extract"); 359 sprintf (buf, "%s/%s", pos, "extract");
353 if (0 == stat(buf, &sbuf)) 360 if (0 == stat (buf, &sbuf))
354 {
355 free (buf);
356 if (NULL == (pos = strdup (pos)))
357 {
358 LOG_STRERROR ("strdup");
359 free (path);
360 return NULL;
361 }
362 free (path);
363 pos = cut_bin (pos);
364 if (NULL == (ret = realloc (pos, strlen (pos) + 6)))
365 {
366 LOG_STRERROR ("realloc");
367 free (pos);
368 return NULL;
369 }
370 strcat (ret, "/lib/");
371 return ret;
372 }
373 pos = end + 1;
374 }
375 sprintf (buf, "%s/%s", pos, "extract");
376 if (0 == stat (buf, &sbuf))
377 { 361 {
378 pos = strdup (pos);
379 free (buf); 362 free (buf);
363 if (NULL == (pos = strdup (pos)))
364 {
365 LOG_STRERROR ("strdup");
366 free (path);
367 return NULL;
368 }
380 free (path); 369 free (path);
381 if (NULL == pos)
382 return NULL;
383 pos = cut_bin (pos); 370 pos = cut_bin (pos);
384 if (NULL == (ret = realloc (pos, strlen (pos) + 6))) 371 if (NULL == (ret = realloc (pos, strlen (pos) + 6)))
385 { 372 {
386 LOG_STRERROR ("realloc"); 373 LOG_STRERROR ("realloc");
387 free (pos); 374 free (pos);
388 return NULL; 375 return NULL;
389 } 376 }
390 strcat (ret, "/lib/"); 377 strcat (ret, "/lib/");
391 return ret; 378 return ret;
392 } 379 }
380 pos = end + 1;
381 }
382 sprintf (buf, "%s/%s", pos, "extract");
383 if (0 == stat (buf, &sbuf))
384 {
385 pos = strdup (pos);
386 free (buf);
387 free (path);
388 if (NULL == pos)
389 return NULL;
390 pos = cut_bin (pos);
391 if (NULL == (ret = realloc (pos, strlen (pos) + 6)))
392 {
393 LOG_STRERROR ("realloc");
394 free (pos);
395 return NULL;
396 }
397 strcat (ret, "/lib/");
398 return ret;
399 }
393 free (buf); 400 free (buf);
394 free (path); 401 free (path);
395 return NULL; 402 return NULL;
@@ -405,7 +412,7 @@ get_path_from_PATH()
405 */ 412 */
406static char * 413static char *
407append_to_dir (const char *path, 414append_to_dir (const char *path,
408 const char *fname) 415 const char *fname)
409{ 416{
410 char *ret; 417 char *ret;
411 size_t slen; 418 size_t slen;
@@ -414,31 +421,31 @@ append_to_dir (const char *path,
414 return NULL; 421 return NULL;
415 if (DIR_SEPARATOR == fname[0]) 422 if (DIR_SEPARATOR == fname[0])
416 fname++; 423 fname++;
417 ret = malloc (slen + strlen(fname) + 2); 424 ret = malloc (slen + strlen (fname) + 2);
418 if (NULL == ret) 425 if (NULL == ret)
419 return NULL; 426 return NULL;
420#ifdef MINGW 427#ifdef MINGW
421 if ('\\' == path[slen-1]) 428 if ('\\' == path[slen - 1])
422 sprintf (ret, 429 sprintf (ret,
423 "%s%s", 430 "%s%s",
424 path, 431 path,
425 fname); 432 fname);
426 else 433 else
427 sprintf (ret, 434 sprintf (ret,
428 "%s\\%s", 435 "%s\\%s",
429 path, 436 path,
430 fname); 437 fname);
431#else 438#else
432 if ('/' == path[slen-1]) 439 if ('/' == path[slen - 1])
433 sprintf (ret, 440 sprintf (ret,
434 "%s%s", 441 "%s%s",
435 path, 442 path,
436 fname); 443 fname);
437 else 444 else
438 sprintf (ret, 445 sprintf (ret,
439 "%s/%s", 446 "%s/%s",
440 path, 447 path,
441 fname); 448 fname);
442#endif 449#endif
443 return ret; 450 return ret;
444} 451}
@@ -453,7 +460,7 @@ append_to_dir (const char *path,
453 */ 460 */
454static void 461static void
455get_installation_paths (EXTRACTOR_PathProcessor pp, 462get_installation_paths (EXTRACTOR_PathProcessor pp,
456 void *pp_cls) 463 void *pp_cls)
457{ 464{
458 const char *p; 465 const char *p;
459 char *path; 466 char *path;
@@ -463,19 +470,19 @@ get_installation_paths (EXTRACTOR_PathProcessor pp,
463 470
464 prefix = NULL; 471 prefix = NULL;
465 if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX"))) 472 if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX")))
473 {
474 if (NULL == (d = strdup (p)))
466 { 475 {
467 if (NULL == (d = strdup (p))) 476 LOG_STRERROR ("strdup");
468 {
469 LOG_STRERROR ("strdup");
470 return;
471 }
472 for (prefix = strtok_r (d, PATH_SEPARATOR_STR, &saveptr);
473 NULL != prefix;
474 prefix = strtok_r (NULL, PATH_SEPARATOR_STR, &saveptr))
475 pp (pp_cls, prefix);
476 free (d);
477 return; 477 return;
478 } 478 }
479 for (prefix = strtok_r (d, PATH_SEPARATOR_STR, &saveptr);
480 NULL != prefix;
481 prefix = strtok_r (NULL, PATH_SEPARATOR_STR, &saveptr))
482 pp (pp_cls, prefix);
483 free (d);
484 return;
485 }
479#if GNU_LINUX 486#if GNU_LINUX
480 if (NULL == prefix) 487 if (NULL == prefix)
481 prefix = get_path_from_proc_exe (); 488 prefix = get_path_from_proc_exe ();
@@ -497,12 +504,12 @@ get_installation_paths (EXTRACTOR_PathProcessor pp,
497 return; 504 return;
498 path = append_to_dir (prefix, PLUGINDIR); 505 path = append_to_dir (prefix, PLUGINDIR);
499 if (NULL != path) 506 if (NULL != path)
500 { 507 {
501 if (0 != strcmp (path, 508 if (0 != strcmp (path,
502 PLUGININSTDIR)) 509 PLUGININSTDIR))
503 pp (pp_cls, path); 510 pp (pp_cls, path);
504 free (path); 511 free (path);
505 } 512 }
506 free (prefix); 513 free (prefix);
507} 514}
508 515
@@ -532,7 +539,7 @@ struct SearchContext
532 */ 539 */
533static void 540static void
534find_plugin_in_path (void *cls, 541find_plugin_in_path (void *cls,
535 const char *path) 542 const char *path)
536{ 543{
537 struct SearchContext *sc = cls; 544 struct SearchContext *sc = cls;
538 DIR *dir; 545 DIR *dir;
@@ -547,34 +554,34 @@ find_plugin_in_path (void *cls,
547 if (NULL == (dir = OPENDIR (path))) 554 if (NULL == (dir = OPENDIR (path)))
548 return; 555 return;
549 while (NULL != (ent = READDIR (dir))) 556 while (NULL != (ent = READDIR (dir)))
557 {
558 if ('.' == ent->d_name[0])
559 continue;
560 dlen = strlen (ent->d_name);
561 if ( (dlen < 4) ||
562 ( (0 != strcmp (&ent->d_name[dlen - 3], ".so")) &&
563 (0 != strcasecmp (&ent->d_name[dlen - 4], ".dll")) ) )
564 continue; /* only load '.so' and '.dll' */
565 if (NULL == (sym_name = strrchr (ent->d_name, '_')))
566 continue;
567 sym_name++;
568 if (NULL == (sym = strdup (sym_name)))
569 {
570 LOG_STRERROR ("strdup");
571 CLOSEDIR (dir);
572 return;
573 }
574 dot = strchr (sym, '.');
575 if (NULL != dot)
576 *dot = '\0';
577 if (0 == strcmp (sym, sc->short_name))
550 { 578 {
551 if ('.' == ent->d_name[0]) 579 sc->path = append_to_dir (path, ent->d_name);
552 continue;
553 dlen = strlen (ent->d_name);
554 if ( (dlen < 4) ||
555 ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) &&
556 (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) )
557 continue; /* only load '.so' and '.dll' */
558 if (NULL == (sym_name = strrchr (ent->d_name, '_')))
559 continue;
560 sym_name++;
561 if (NULL == (sym = strdup (sym_name)))
562 {
563 LOG_STRERROR ("strdup");
564 CLOSEDIR (dir);
565 return;
566 }
567 dot = strchr (sym, '.');
568 if (NULL != dot)
569 *dot = '\0';
570 if (0 == strcmp (sym, sc->short_name))
571 {
572 sc->path = append_to_dir (path, ent->d_name);
573 free (sym);
574 break;
575 }
576 free (sym); 580 free (sym);
581 break;
577 } 582 }
583 free (sym);
584 }
578 CLOSEDIR (dir); 585 CLOSEDIR (dir);
579} 586}
580 587
@@ -591,7 +598,7 @@ EXTRACTOR_find_plugin_ (const char *short_name)
591 sc.path = NULL; 598 sc.path = NULL;
592 sc.short_name = short_name; 599 sc.short_name = short_name;
593 get_installation_paths (&find_plugin_in_path, 600 get_installation_paths (&find_plugin_in_path,
594 &sc); 601 &sc);
595 return sc.path; 602 return sc.path;
596} 603}
597 604
@@ -621,7 +628,7 @@ struct DefaultLoaderContext
621 */ 628 */
622static void 629static void
623load_plugins_from_dir (void *cls, 630load_plugins_from_dir (void *cls,
624 const char *path) 631 const char *path)
625{ 632{
626 struct DefaultLoaderContext *dlc = cls; 633 struct DefaultLoaderContext *dlc = cls;
627 DIR *dir; 634 DIR *dir;
@@ -634,31 +641,31 @@ load_plugins_from_dir (void *cls,
634 if (NULL == (dir = opendir (path))) 641 if (NULL == (dir = opendir (path)))
635 return; 642 return;
636 while (NULL != (ent = readdir (dir))) 643 while (NULL != (ent = readdir (dir)))
644 {
645 if (ent->d_name[0] == '.')
646 continue;
647 dlen = strlen (ent->d_name);
648 if ( (dlen < 4) ||
649 ( (0 != strcmp (&ent->d_name[dlen - 3], ".so")) &&
650 (0 != strcasecmp (&ent->d_name[dlen - 4], ".dll")) ) )
651 continue; /* only load '.so' and '.dll' */
652 if (NULL == (sym_name = strrchr (ent->d_name, '_')))
653 continue;
654 sym_name++;
655 if (NULL == (sym = strdup (sym_name)))
637 { 656 {
638 if (ent->d_name[0] == '.') 657 LOG_STRERROR ("strdup");
639 continue; 658 closedir (dir);
640 dlen = strlen (ent->d_name); 659 return;
641 if ( (dlen < 4) ||
642 ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) &&
643 (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) )
644 continue; /* only load '.so' and '.dll' */
645 if (NULL == (sym_name = strrchr (ent->d_name, '_')))
646 continue;
647 sym_name++;
648 if (NULL == (sym = strdup (sym_name)))
649 {
650 LOG_STRERROR ("strdup");
651 closedir (dir);
652 return;
653 }
654 if (NULL != (dot = strchr (sym, '.')))
655 *dot = '\0';
656 dlc->res = EXTRACTOR_plugin_add (dlc->res,
657 sym,
658 NULL,
659 dlc->flags);
660 free (sym);
661 } 660 }
661 if (NULL != (dot = strchr (sym, '.')))
662 *dot = '\0';
663 dlc->res = EXTRACTOR_plugin_add (dlc->res,
664 sym,
665 NULL,
666 dlc->flags);
667 free (sym);
668 }
662 closedir (dir); 669 closedir (dir);
663} 670}
664 671
@@ -685,7 +692,7 @@ EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags)
685 dlc.res = NULL; 692 dlc.res = NULL;
686 dlc.flags = flags; 693 dlc.flags = flags;
687 get_installation_paths (&load_plugins_from_dir, 694 get_installation_paths (&load_plugins_from_dir,
688 &dlc); 695 &dlc);
689 return dlc.res; 696 return dlc.res;
690} 697}
691 698
diff --git a/src/main/extractor_plugpath.h b/src/main/extractor_plugpath.h
index 848be52..3a3b217 100644
--- a/src/main/extractor_plugpath.h
+++ b/src/main/extractor_plugpath.h
@@ -29,9 +29,9 @@
29 * Given a short name of a library (i.e. "mime"), find 29 * Given a short name of a library (i.e. "mime"), find
30 * the full path of the respective plugin. 30 * the full path of the respective plugin.
31 */ 31 */
32char * 32char *
33EXTRACTOR_find_plugin_ (const char *short_name); 33EXTRACTOR_find_plugin_ (const char *short_name);
34 34
35 35
36#endif 36#endif
37/* EXTRACTOR_PLUGPATH_H */ 37/* EXTRACTOR_PLUGPATH_H */
diff --git a/src/main/extractor_print.c b/src/main/extractor_print.c
index 3530430..a89b522 100644
--- a/src/main/extractor_print.c
+++ b/src/main/extractor_print.c
@@ -33,72 +33,73 @@
33 * Simple EXTRACTOR_MetaDataProcessor implementation that simply 33 * Simple EXTRACTOR_MetaDataProcessor implementation that simply
34 * prints the extracted meta data to the given file. Only prints 34 * prints the extracted meta data to the given file. Only prints
35 * those keywords that are in UTF-8 format. 35 * those keywords that are in UTF-8 format.
36 * 36 *
37 * @param handle the file to write to (stdout, stderr), must NOT be NULL, 37 * @param handle the file to write to (stdout, stderr), must NOT be NULL,
38 * must be of type "FILE *". 38 * must be of type "FILE *".
39 * @param plugin_name name of the plugin that produced this value 39 * @param plugin_name name of the plugin that produced this value
40 * @param type libextractor-type describing the meta data 40 * @param type libextractor-type describing the meta data
41 * @param format basic format information about data 41 * @param format basic format information about data
42 * @param data_mime_type mime-type of data (not of the original file); 42 * @param data_mime_type mime-type of data (not of the original file);
43 * can be NULL (if mime-type is not known) 43 * can be NULL (if mime-type is not known)
44 * @param data actual meta-data found 44 * @param data actual meta-data found
45 * @param data_len number of bytes in data 45 * @param data_len number of bytes in data
46 * @return non-zero if printing failed, otherwise 0. 46 * @return non-zero if printing failed, otherwise 0.
47 */ 47 */
48int 48int
49EXTRACTOR_meta_data_print (void *handle, 49EXTRACTOR_meta_data_print (void *handle,
50 const char *plugin_name, 50 const char *plugin_name,
51 enum EXTRACTOR_MetaType type, 51 enum EXTRACTOR_MetaType type,
52 enum EXTRACTOR_MetaFormat format, 52 enum EXTRACTOR_MetaFormat format,
53 const char *data_mime_type, 53 const char *data_mime_type,
54 const char *data, 54 const char *data,
55 size_t data_len) 55 size_t data_len)
56{ 56{
57#if HAVE_ICONV 57#if HAVE_ICONV
58 iconv_t cd; 58 iconv_t cd;
59#endif 59#endif
60 char * buf; 60 char *buf;
61 int ret; 61 int ret;
62 const char *mt; 62 const char *mt;
63 63
64 if (EXTRACTOR_METAFORMAT_UTF8 != format) 64 if (EXTRACTOR_METAFORMAT_UTF8 != format)
65 return 0; 65 return 0;
66#if HAVE_ICONV 66#if HAVE_ICONV
67 cd = iconv_open (nl_langinfo(CODESET), 67 cd = iconv_open (nl_langinfo (CODESET),
68 "UTF-8"); 68 "UTF-8");
69 if (((iconv_t) -1) == cd) 69 if (((iconv_t) -1) == cd)
70 { 70 {
71 LOG_STRERROR ("iconv_open"); 71 LOG_STRERROR ("iconv_open");
72 return 1; 72 return 1;
73 } 73 }
74 buf = iconv_helper (cd, data, data_len); 74 buf = iconv_helper (cd, data, data_len);
75 if (NULL == buf) 75 if (NULL == buf)
76 { 76 {
77 LOG_STRERROR ("iconv_helper"); 77 LOG_STRERROR ("iconv_helper");
78 ret = -1; 78 ret = -1;
79 } 79 }
80 else 80 else
81 { 81 {
82 mt = EXTRACTOR_metatype_to_string (type); 82 mt = EXTRACTOR_metatype_to_string (type);
83 ret = fprintf (handle, 83 ret = fprintf (handle,
84 "%s - %s\n", 84 "%s - %s\n",
85 (NULL == mt) 85 (NULL == mt)
86 ? dgettext ("libextractor", gettext_noop ("unknown")) 86 ? dgettext ("libextractor", gettext_noop ("unknown"))
87 : dgettext ("libextractor", mt), 87 : dgettext ("libextractor", mt),
88 buf); 88 buf);
89 free(buf); 89 free (buf);
90 } 90 }
91 iconv_close(cd); 91 iconv_close (cd);
92#else 92#else
93 ret = fprintf (handle, 93 ret = fprintf (handle,
94 "%s - %.*s\n", 94 "%s - %.*s\n",
95 (NULL == mt) 95 (NULL == mt)
96 ? dgettext ("libextractor", gettext_noop ("unknown")) 96 ? dgettext ("libextractor", gettext_noop ("unknown"))
97 : dgettext ("libextractor", mt), 97 : dgettext ("libextractor", mt),
98 (int) data_len, 98 (int) data_len,
99 data); 99 data);
100#endif 100#endif
101 return (ret < 0) ? 1 : 0; 101 return (ret < 0) ? 1 : 0;
102} 102}
103 103
104
104/* end of extractor_print.c */ 105/* end of extractor_print.c */
diff --git a/src/main/getopt.c b/src/main/getopt.c
index b64fdf5..890aa9b 100644
--- a/src/main/getopt.c
+++ b/src/main/getopt.c
@@ -4,7 +4,7 @@
4 before changing it! 4 before changing it!
5 5
6 Copyright Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 6 Copyright Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
7 Free Software Foundation, Inc. 7 Free Software Foundation, Inc.
8 8
9NOTE: The canonical source of this file is maintained with the GNU C Library. 9NOTE: The canonical source of this file is maintained with the GNU C Library.
10Bugs can be reported to bug-glibc@prep.ai.mit.edu. 10Bugs can be reported to bug-glibc@prep.ai.mit.edu.
@@ -32,7 +32,7 @@ USA. */
32 32
33#include "config.h" 33#include "config.h"
34 34
35#if !defined (__STDC__) || !__STDC__ 35#if ! defined (__STDC__) || ! __STDC__
36/* This is a separate conditional since some stdc systems 36/* This is a separate conditional since some stdc systems
37 reject `defined (const)'. */ 37 reject `defined (const)'. */
38#ifndef const 38#ifndef const
@@ -51,7 +51,7 @@ USA. */
51 it is simpler to just do this in the source for each such file. */ 51 it is simpler to just do this in the source for each such file. */
52 52
53#define GETOPT_INTERFACE_VERSION 2 53#define GETOPT_INTERFACE_VERSION 2
54#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 54#if ! defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
55#include <gnu-versions.h> 55#include <gnu-versions.h>
56#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION 56#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
57#define ELIDE_CODE 57#define ELIDE_CODE
@@ -63,7 +63,7 @@ USA. */
63 63
64/* This needs to come after some library #include 64/* This needs to come after some library #include
65 to get __GNU_LIBRARY__ defined. */ 65 to get __GNU_LIBRARY__ defined. */
66#ifdef __GNU_LIBRARY__ 66#ifdef __GNU_LIBRARY__
67/* Don't include stdlib.h for non-GNU C libraries because some of them 67/* Don't include stdlib.h for non-GNU C libraries because some of them
68 contain conflicting prototypes for getopt. */ 68 contain conflicting prototypes for getopt. */
69#include <stdlib.h> 69#include <stdlib.h>
@@ -77,10 +77,10 @@ USA. */
77#include <string.h> 77#include <string.h>
78#endif 78#endif
79 79
80#if defined (WIN32) && !defined (__CYGWIN32__) 80#if defined (WIN32) && ! defined (__CYGWIN32__)
81/* It's not Unix, really. See? Capital letters. */ 81/* It's not Unix, really. See? Capital letters. */
82#include <windows.h> 82#include <windows.h>
83#define getpid() GetCurrentProcessId() 83#define getpid() GetCurrentProcessId ()
84#endif 84#endif
85 85
86#ifndef _ 86#ifndef _
@@ -88,9 +88,9 @@ USA. */
88 When compiling libc, the _ macro is predefined. */ 88 When compiling libc, the _ macro is predefined. */
89#ifdef NEVER_HAVE_LIBINTL_H 89#ifdef NEVER_HAVE_LIBINTL_H
90# include <libintl.h> 90# include <libintl.h>
91# define _(msgid) gettext (msgid) 91# define _(msgid) gettext (msgid)
92#else 92#else
93# define _(msgid) (msgid) 93# define _(msgid) (msgid)
94#endif 94#endif
95#endif 95#endif
96 96
@@ -195,14 +195,14 @@ static enum
195 195
196/* Value of POSIXLY_CORRECT environment variable. */ 196/* Value of POSIXLY_CORRECT environment variable. */
197static char *posixly_correct; 197static char *posixly_correct;
198 198
199#ifdef __GNU_LIBRARY__ 199#ifdef __GNU_LIBRARY__
200/* We want to avoid inclusion of string.h with non-GNU libraries 200/* We want to avoid inclusion of string.h with non-GNU libraries
201 because there are many ways it can cause trouble. 201 because there are many ways it can cause trouble.
202 On some systems, it contains special magic macros that don't work 202 On some systems, it contains special magic macros that don't work
203 in GCC. */ 203 in GCC. */
204#include <string.h> 204#include <string.h>
205#define my_index strchr 205#define my_index strchr
206#else 206#else
207 207
208/* Avoid depending on library functions or files 208/* Avoid depending on library functions or files
@@ -212,15 +212,16 @@ char *getenv ();
212 212
213static char * 213static char *
214my_index (str, chr) 214my_index (str, chr)
215 const char *str; 215const char *str;
216 int chr; 216
217int chr;
217{ 218{
218 while (*str) 219 while (*str)
219 { 220 {
220 if (*str == chr) 221 if (*str == chr)
221 return (char *) str; 222 return (char *) str;
222 str++; 223 str++;
223 } 224 }
224 return 0; 225 return 0;
225} 226}
226 227
@@ -229,18 +230,20 @@ my_index (str, chr)
229#ifdef __GNUC__ 230#ifdef __GNUC__
230/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. 231/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
231 That was relevant to code that was here before. */ 232 That was relevant to code that was here before. */
232#if !defined (__STDC__) || !__STDC__ 233#if ! defined (__STDC__) || ! __STDC__
233/* gcc with -traditional declares the built-in strlen to return int, 234/* gcc with -traditional declares the built-in strlen to return int,
234 and has done so at least since version 2.4.5. -- rms. */ 235 and has done so at least since version 2.4.5. -- rms. */
235extern int strlen (const char *); 236extern int strlen (const char *);
237
236#endif /* not __STDC__ */ 238#endif /* not __STDC__ */
237#if defined(__APPLE__) 239#if defined(__APPLE__)
238extern size_t strlen (const char *); 240extern size_t strlen (const char *);
241
239#endif 242#endif
240#endif /* __GNUC__ */ 243#endif /* __GNUC__ */
241 244
242#endif /* not __GNU_LIBRARY__ */ 245#endif /* not __GNU_LIBRARY__ */
243 246
244/* Handle permutation of arguments. */ 247/* Handle permutation of arguments. */
245 248
246/* Describe the part of ARGV that contains non-options that have 249/* Describe the part of ARGV that contains non-options that have
@@ -269,7 +272,8 @@ extern pid_t __libc_pid;
269 is valid for the getopt call we must make sure that the ARGV passed 272 is valid for the getopt call we must make sure that the ARGV passed
270 to getopt is that one passed to the process. */ 273 to getopt is that one passed to the process. */
271static void 274static void
272 __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) 275__attribute__ ((unused))
276store_args_and_env (int argc, char *const *argv)
273{ 277{
274 /* XXX This is no good solution. We should rather copy the args so 278 /* XXX This is no good solution. We should rather copy the args so
275 that we can compare them later. But we must not use malloc(3). */ 279 that we can compare them later. But we must not use malloc(3). */
@@ -277,15 +281,16 @@ static void
277 original_argv = argv; 281 original_argv = argv;
278} 282}
279 283
284
280text_set_element (__libc_subinit, store_args_and_env); 285text_set_element (__libc_subinit, store_args_and_env);
281 286
282# define SWAP_FLAGS(ch1, ch2) \ 287# define SWAP_FLAGS(ch1, ch2) \
283 if (nonoption_flags_len > 0) \ 288 if (nonoption_flags_len > 0) \
284 { \ 289 { \
285 char __tmp = __getopt_nonoption_flags[ch1]; \ 290 char __tmp = __getopt_nonoption_flags[ch1]; \
286 __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ 291 __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
287 __getopt_nonoption_flags[ch2] = __tmp; \ 292 __getopt_nonoption_flags[ch2] = __tmp; \
288 } 293 }
289#else /* !_LIBC */ 294#else /* !_LIBC */
290# define SWAP_FLAGS(ch1, ch2) 295# define SWAP_FLAGS(ch1, ch2)
291#endif /* _LIBC */ 296#endif /* _LIBC */
@@ -301,11 +306,13 @@ text_set_element (__libc_subinit, store_args_and_env);
301 306
302#if defined (__STDC__) && __STDC__ 307#if defined (__STDC__) && __STDC__
303static void exchange (char **); 308static void exchange (char **);
309
304#endif 310#endif
305 311
306static void 312static void
307exchange (argv) 313exchange (argv)
308 char **argv; 314char **argv;
315
309{ 316{
310 int bottom = first_nonopt; 317 int bottom = first_nonopt;
311 int middle = last_nonopt; 318 int middle = last_nonopt;
@@ -321,61 +328,61 @@ exchange (argv)
321 /* First make sure the handling of the `__getopt_nonoption_flags' 328 /* First make sure the handling of the `__getopt_nonoption_flags'
322 string can work normally. Our top argument must be in the range 329 string can work normally. Our top argument must be in the range
323 of the string. */ 330 of the string. */
324 if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) 331 if ((nonoption_flags_len > 0) && (top >= nonoption_flags_max_len))
332 {
333 /* We must extend the array. The user plays games with us and
334 presents new arguments. */
335 char *new_str = malloc (top + 1);
336 if (new_str == NULL)
337 nonoption_flags_len = nonoption_flags_max_len = 0;
338 else
325 { 339 {
326 /* We must extend the array. The user plays games with us and 340 memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
327 presents new arguments. */ 341 memset (&new_str[nonoption_flags_max_len], '\0',
328 char *new_str = malloc (top + 1); 342 top + 1 - nonoption_flags_max_len);
329 if (new_str == NULL) 343 nonoption_flags_max_len = top + 1;
330 nonoption_flags_len = nonoption_flags_max_len = 0; 344 __getopt_nonoption_flags = new_str;
331 else
332 {
333 memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
334 memset (&new_str[nonoption_flags_max_len], '\0',
335 top + 1 - nonoption_flags_max_len);
336 nonoption_flags_max_len = top + 1;
337 __getopt_nonoption_flags = new_str;
338 }
339 } 345 }
346 }
340#endif 347#endif
341 348
342 while (top > middle && middle > bottom) 349 while (top > middle && middle > bottom)
350 {
351 if (top - middle > middle - bottom)
343 { 352 {
344 if (top - middle > middle - bottom) 353 /* Bottom segment is the short one. */
345 { 354 int len = middle - bottom;
346 /* Bottom segment is the short one. */ 355 register int i;
347 int len = middle - bottom; 356
348 register int i; 357 /* Swap it with the top part of the top segment. */
349 358 for (i = 0; i < len; i++)
350 /* Swap it with the top part of the top segment. */ 359 {
351 for (i = 0; i < len; i++) 360 tem = argv[bottom + i];
352 { 361 argv[bottom + i] = argv[top - (middle - bottom) + i];
353 tem = argv[bottom + i]; 362 argv[top - (middle - bottom) + i] = tem;
354 argv[bottom + i] = argv[top - (middle - bottom) + i]; 363 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
355 argv[top - (middle - bottom) + i] = tem; 364 }
356 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); 365 /* Exclude the moved bottom segment from further swapping. */
357 } 366 top -= len;
358 /* Exclude the moved bottom segment from further swapping. */ 367 }
359 top -= len; 368 else
360 } 369 {
361 else 370 /* Top segment is the short one. */
362 { 371 int len = top - middle;
363 /* Top segment is the short one. */ 372 register int i;
364 int len = top - middle; 373
365 register int i; 374 /* Swap it with the bottom part of the bottom segment. */
366 375 for (i = 0; i < len; i++)
367 /* Swap it with the bottom part of the bottom segment. */ 376 {
368 for (i = 0; i < len; i++) 377 tem = argv[bottom + i];
369 { 378 argv[bottom + i] = argv[middle + i];
370 tem = argv[bottom + i]; 379 argv[middle + i] = tem;
371 argv[bottom + i] = argv[middle + i]; 380 SWAP_FLAGS (bottom + i, middle + i);
372 argv[middle + i] = tem; 381 }
373 SWAP_FLAGS (bottom + i, middle + i); 382 /* Exclude the moved top segment from further swapping. */
374 } 383 bottom += len;
375 /* Exclude the moved top segment from further swapping. */
376 bottom += len;
377 }
378 } 384 }
385 }
379 386
380 /* Update records for the slots the non-options now occupy. */ 387 /* Update records for the slots the non-options now occupy. */
381 388
@@ -387,12 +394,14 @@ exchange (argv)
387 394
388#if defined (__STDC__) && __STDC__ 395#if defined (__STDC__) && __STDC__
389static const char *_getopt_initialize (int, char *const *, const char *); 396static const char *_getopt_initialize (int, char *const *, const char *);
397
390#endif 398#endif
391static const char * 399static const char *
392_getopt_initialize (argc, argv, optstring) 400_getopt_initialize (argc, argv, optstring)
393 int argc; 401int argc;
394 char *const *argv; 402
395 const char *optstring; 403char *const *argv;
404const char *optstring;
396{ 405{
397 /* Start processing options with ARGV-element 1 (since ARGV-element 0 406 /* Start processing options with ARGV-element 1 (since ARGV-element 0
398 is the program name); the sequence of previously skipped 407 is the program name); the sequence of previously skipped
@@ -407,56 +416,56 @@ _getopt_initialize (argc, argv, optstring)
407 /* Determine how to handle the ordering of options and nonoptions. */ 416 /* Determine how to handle the ordering of options and nonoptions. */
408 417
409 if (optstring[0] == '-') 418 if (optstring[0] == '-')
410 { 419 {
411 ordering = RETURN_IN_ORDER; 420 ordering = RETURN_IN_ORDER;
412 ++optstring; 421 ++optstring;
413 } 422 }
414 else if (optstring[0] == '+') 423 else if (optstring[0] == '+')
415 { 424 {
416 ordering = REQUIRE_ORDER; 425 ordering = REQUIRE_ORDER;
417 ++optstring; 426 ++optstring;
418 } 427 }
419 else if (posixly_correct != NULL) 428 else if (posixly_correct != NULL)
420 ordering = REQUIRE_ORDER; 429 ordering = REQUIRE_ORDER;
421 else 430 else
422 ordering = PERMUTE; 431 ordering = PERMUTE;
423 432
424#ifdef _LIBC 433#ifdef _LIBC
425 if (posixly_correct == NULL 434 if ((posixly_correct == NULL)
426 && argc == original_argc && argv == original_argv) 435 && (argc == original_argc) && (argv == original_argv))
436 {
437 if (nonoption_flags_max_len == 0)
427 { 438 {
428 if (nonoption_flags_max_len == 0) 439 if ((__getopt_nonoption_flags == NULL)
429 { 440 || (__getopt_nonoption_flags[0] == '\0') )
430 if (__getopt_nonoption_flags == NULL 441 nonoption_flags_max_len = -1;
431 || __getopt_nonoption_flags[0] == '\0') 442 else
432 nonoption_flags_max_len = -1; 443 {
433 else 444 const char *orig_str = __getopt_nonoption_flags;
434 { 445 int len = nonoption_flags_max_len = strlen (orig_str);
435 const char *orig_str = __getopt_nonoption_flags; 446 if (nonoption_flags_max_len < argc)
436 int len = nonoption_flags_max_len = strlen (orig_str); 447 nonoption_flags_max_len = argc;
437 if (nonoption_flags_max_len < argc) 448 __getopt_nonoption_flags =
438 nonoption_flags_max_len = argc; 449 (char *) malloc (nonoption_flags_max_len);
439 __getopt_nonoption_flags = 450 if (__getopt_nonoption_flags == NULL)
440 (char *) malloc (nonoption_flags_max_len); 451 nonoption_flags_max_len = -1;
441 if (__getopt_nonoption_flags == NULL) 452 else
442 nonoption_flags_max_len = -1; 453 {
443 else 454 memcpy (__getopt_nonoption_flags, orig_str, len);
444 { 455 memset (&__getopt_nonoption_flags[len], '\0',
445 memcpy (__getopt_nonoption_flags, orig_str, len); 456 nonoption_flags_max_len - len);
446 memset (&__getopt_nonoption_flags[len], '\0', 457 }
447 nonoption_flags_max_len - len); 458 }
448 }
449 }
450 }
451 nonoption_flags_len = nonoption_flags_max_len;
452 } 459 }
460 nonoption_flags_len = nonoption_flags_max_len;
461 }
453 else 462 else
454 nonoption_flags_len = 0; 463 nonoption_flags_len = 0;
455#endif 464#endif
456 465
457 return optstring; 466 return optstring;
458} 467}
459 468
460/* Scan elements of ARGV (whose length is ARGC) for option characters 469/* Scan elements of ARGV (whose length is ARGC) for option characters
461 given in OPTSTRING. 470 given in OPTSTRING.
462 471
@@ -515,112 +524,113 @@ _getopt_initialize (argc, argv, optstring)
515 524
516int 525int
517_getopt_internal (argc, argv, optstring, longopts, longind, long_only) 526_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
518 int argc; 527int argc;
519 char *const *argv; 528
520 const char *optstring; 529char *const *argv;
521 const struct option *longopts; 530const char *optstring;
522 int *longind; 531const struct option *longopts;
523 int long_only; 532int *longind;
533int long_only;
524{ 534{
525 optarg = NULL; 535 optarg = NULL;
526 536
527 if (optind == 0 || !__getopt_initialized) 537 if ((optind == 0) || ! __getopt_initialized)
528 { 538 {
529 if (optind == 0) 539 if (optind == 0)
530 optind = 1; /* Don't scan ARGV[0], the program name. */ 540 optind = 1; /* Don't scan ARGV[0], the program name. */
531 optstring = _getopt_initialize (argc, argv, optstring); 541 optstring = _getopt_initialize (argc, argv, optstring);
532 __getopt_initialized = 1; 542 __getopt_initialized = 1;
533 } 543 }
534 544
535 /* Test whether ARGV[optind] points to a non-option argument. 545 /* Test whether ARGV[optind] points to a non-option argument.
536 Either it does not have option syntax, or there is an environment flag 546 Either it does not have option syntax, or there is an environment flag
537 from the shell indicating it is not an option. The later information 547 from the shell indicating it is not an option. The later information
538 is only used when the used in the GNU libc. */ 548 is only used when the used in the GNU libc. */
539#ifdef _LIBC 549#ifdef _LIBC
540#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ 550#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
541 || (optind < nonoption_flags_len \ 551 || (optind < nonoption_flags_len \
542 && __getopt_nonoption_flags[optind] == '1')) 552 && __getopt_nonoption_flags[optind] == '1'))
543#else 553#else
544#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') 554#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
545#endif 555#endif
546 556
547 if (nextchar == NULL || *nextchar == '\0') 557 if ((nextchar == NULL) || (*nextchar == '\0'))
558 {
559 /* Advance to the next ARGV-element. */
560
561 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
562 moved back by the user (who may also have changed the arguments). */
563 if (last_nonopt > optind)
564 last_nonopt = optind;
565 if (first_nonopt > optind)
566 first_nonopt = optind;
567
568 if (ordering == PERMUTE)
548 { 569 {
549 /* Advance to the next ARGV-element. */ 570 /* If we have just processed some options following some non-options,
550 571 exchange them so that the options come first. */
551 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been 572
552 moved back by the user (who may also have changed the arguments). */ 573 if ((first_nonopt != last_nonopt) && (last_nonopt != optind) )
553 if (last_nonopt > optind) 574 exchange ((char **) argv);
554 last_nonopt = optind; 575 else if (last_nonopt != optind)
555 if (first_nonopt > optind) 576 first_nonopt = optind;
556 first_nonopt = optind; 577
557 578 /* Skip any additional non-options
558 if (ordering == PERMUTE) 579 and extend the range of non-options previously skipped. */
559 { 580
560 /* If we have just processed some options following some non-options, 581 while (optind < argc && NONOPTION_P)
561 exchange them so that the options come first. */ 582 optind++;
562 583 last_nonopt = optind;
563 if (first_nonopt != last_nonopt && last_nonopt != optind)
564 exchange ((char **) argv);
565 else if (last_nonopt != optind)
566 first_nonopt = optind;
567
568 /* Skip any additional non-options
569 and extend the range of non-options previously skipped. */
570
571 while (optind < argc && NONOPTION_P)
572 optind++;
573 last_nonopt = optind;
574 }
575
576 /* The special ARGV-element `--' means premature end of options.
577 Skip it like a null option,
578 then exchange with previous non-options as if it were an option,
579 then skip everything else like a non-option. */
580
581 if (optind != argc && !strcmp (argv[optind], "--"))
582 {
583 optind++;
584
585 if (first_nonopt != last_nonopt && last_nonopt != optind)
586 exchange ((char **) argv);
587 else if (first_nonopt == last_nonopt)
588 first_nonopt = optind;
589 last_nonopt = argc;
590
591 optind = argc;
592 }
593
594 /* If we have done all the ARGV-elements, stop the scan
595 and back over any non-options that we skipped and permuted. */
596
597 if (optind == argc)
598 {
599 /* Set the next-arg-index to point at the non-options
600 that we previously skipped, so the caller will digest them. */
601 if (first_nonopt != last_nonopt)
602 optind = first_nonopt;
603 return -1;
604 }
605
606 /* If we have come to a non-option and did not permute it,
607 either stop the scan or describe it to the caller and pass it by. */
608
609 if (NONOPTION_P)
610 {
611 if (ordering == REQUIRE_ORDER)
612 return -1;
613 optarg = argv[optind++];
614 return 1;
615 }
616
617 /* We have found another option-ARGV-element.
618 Skip the initial punctuation. */
619
620 nextchar = (argv[optind] + 1
621 + (longopts != NULL && argv[optind][1] == '-'));
622 } 584 }
623 585
586 /* The special ARGV-element `--' means premature end of options.
587 Skip it like a null option,
588 then exchange with previous non-options as if it were an option,
589 then skip everything else like a non-option. */
590
591 if ((optind != argc) && ! strcmp (argv[optind], "--"))
592 {
593 optind++;
594
595 if ((first_nonopt != last_nonopt) && (last_nonopt != optind) )
596 exchange ((char **) argv);
597 else if (first_nonopt == last_nonopt)
598 first_nonopt = optind;
599 last_nonopt = argc;
600
601 optind = argc;
602 }
603
604 /* If we have done all the ARGV-elements, stop the scan
605 and back over any non-options that we skipped and permuted. */
606
607 if (optind == argc)
608 {
609 /* Set the next-arg-index to point at the non-options
610 that we previously skipped, so the caller will digest them. */
611 if (first_nonopt != last_nonopt)
612 optind = first_nonopt;
613 return -1;
614 }
615
616 /* If we have come to a non-option and did not permute it,
617 either stop the scan or describe it to the caller and pass it by. */
618
619 if (NONOPTION_P)
620 {
621 if (ordering == REQUIRE_ORDER)
622 return -1;
623 optarg = argv[optind++];
624 return 1;
625 }
626
627 /* We have found another option-ARGV-element.
628 Skip the initial punctuation. */
629
630 nextchar = (argv[optind] + 1
631 + (longopts != NULL && argv[optind][1] == '-'));
632 }
633
624 /* Decode the current option-ARGV-element. */ 634 /* Decode the current option-ARGV-element. */
625 635
626 /* Check whether the ARGV-element is a long option. 636 /* Check whether the ARGV-element is a long option.
@@ -636,141 +646,141 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
636 646
637 This distinction seems to be the most useful approach. */ 647 This distinction seems to be the most useful approach. */
638 648
639 if (longopts != NULL 649 if ((longopts != NULL)
640 && (argv[optind][1] == '-' 650 && ((argv[optind][1] == '-')
641 || (long_only 651 || (long_only
642 && (argv[optind][2] 652 && (argv[optind][2]
643 || !my_index (optstring, argv[optind][1]))))) 653 || ! my_index (optstring, argv[optind][1])))))
644 { 654 {
645 char *nameend; 655 char *nameend;
646 const struct option *p; 656 const struct option *p;
647 const struct option *pfound = NULL; 657 const struct option *pfound = NULL;
648 int exact = 0; 658 int exact = 0;
649 int ambig = 0; 659 int ambig = 0;
650 int indfound = -1; 660 int indfound = -1;
651 int option_index; 661 int option_index;
662
663 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
664 /* Do nothing. */;
665
666 /* Test all long options for either exact match
667 or abbreviated matches. */
668 for (p = longopts, option_index = 0; p->name; p++, option_index++)
669 if (! strncmp (p->name, nextchar, nameend - nextchar))
670 {
671 if ((unsigned int) (nameend - nextchar)
672 == (unsigned int) strlen (p->name))
673 {
674 /* Exact match found. */
675 pfound = p;
676 indfound = option_index;
677 exact = 1;
678 break;
679 }
680 else if (pfound == NULL)
681 {
682 /* First nonexact match found. */
683 pfound = p;
684 indfound = option_index;
685 }
686 else
687 /* Second or later nonexact match found. */
688 ambig = 1;
689 }
652 690
653 for (nameend = nextchar; *nameend && *nameend != '='; nameend++) 691 if (ambig && ! exact)
654 /* Do nothing. */ ; 692 {
693 if (opterr)
694 fprintf (stderr, _ ("%s: option `%s' is ambiguous\n"),
695 argv[0], argv[optind]);
696 nextchar += strlen (nextchar);
697 optind++;
698 optopt = 0;
699 return '?';
700 }
655 701
656 /* Test all long options for either exact match 702 if (pfound != NULL)
657 or abbreviated matches. */ 703 {
658 for (p = longopts, option_index = 0; p->name; p++, option_index++) 704 option_index = indfound;
659 if (!strncmp (p->name, nextchar, nameend - nextchar)) 705 optind++;
660 { 706 if (*nameend)
661 if ((unsigned int) (nameend - nextchar) 707 {
662 == (unsigned int) strlen (p->name)) 708 /* Don't test has_arg with >, because some C compilers don't
663 { 709 allow it to be used on enums. */
664 /* Exact match found. */ 710 if (pfound->has_arg)
665 pfound = p; 711 optarg = nameend + 1;
666 indfound = option_index; 712 else
667 exact = 1; 713 {
668 break; 714 if (opterr)
669 } 715 if (argv[optind - 1][1] == '-')
670 else if (pfound == NULL) 716 /* --option */
671 { 717 fprintf (stderr,
672 /* First nonexact match found. */ 718 _
673 pfound = p; 719 ("%s: option `--%s' doesn't allow an argument\n"),
674 indfound = option_index; 720 argv[0], pfound->name);
675 } 721 else
676 else 722 /* +option or -option */
677 /* Second or later nonexact match found. */ 723 fprintf (stderr,
678 ambig = 1; 724 _
679 } 725 ("%s: option `%c%s' doesn't allow an argument\n"),
680 726 argv[0], argv[optind - 1][0], pfound->name);
681 if (ambig && !exact) 727
682 { 728 nextchar += strlen (nextchar);
683 if (opterr) 729
684 fprintf (stderr, _("%s: option `%s' is ambiguous\n"), 730 optopt = pfound->val;
685 argv[0], argv[optind]); 731 return '?';
686 nextchar += strlen (nextchar); 732 }
687 optind++; 733 }
688 optopt = 0; 734 else if (pfound->has_arg == 1)
689 return '?'; 735 {
690 } 736 if (optind < argc)
737 optarg = argv[optind++];
738 else
739 {
740 if (opterr)
741 fprintf (stderr,
742 _ ("%s: option `%s' requires an argument\n"),
743 argv[0], argv[optind - 1]);
744 nextchar += strlen (nextchar);
745 optopt = pfound->val;
746 return optstring[0] == ':' ? ':' : '?';
747 }
748 }
749 nextchar += strlen (nextchar);
750 if (longind != NULL)
751 *longind = option_index;
752 if (pfound->flag)
753 {
754 *(pfound->flag) = pfound->val;
755 return 0;
756 }
757 return pfound->val;
758 }
691 759
692 if (pfound != NULL) 760 /* Can't find it as a long option. If this is not getopt_long_only,
693 { 761 or the option starts with '--' or is not a valid short
694 option_index = indfound; 762 option, then it's an error.
695 optind++; 763 Otherwise interpret it as a short option. */
696 if (*nameend) 764 if (! long_only || (argv[optind][1] == '-')
697 { 765 || (my_index (optstring, *nextchar) == NULL) )
698 /* Don't test has_arg with >, because some C compilers don't 766 {
699 allow it to be used on enums. */ 767 if (opterr)
700 if (pfound->has_arg) 768 {
701 optarg = nameend + 1; 769 if (argv[optind][1] == '-')
702 else 770 /* --option */
703 { 771 fprintf (stderr, _ ("%s: unrecognized option `--%s'\n"),
704 if (opterr) 772 argv[0], nextchar);
705 if (argv[optind - 1][1] == '-') 773 else
706 /* --option */ 774 /* +option or -option */
707 fprintf (stderr, 775 fprintf (stderr, _ ("%s: unrecognized option `%c%s'\n"),
708 _ 776 argv[0], argv[optind][0], nextchar);
709 ("%s: option `--%s' doesn't allow an argument\n"), 777 }
710 argv[0], pfound->name); 778 nextchar = (char *) "";
711 else 779 optind++;
712 /* +option or -option */ 780 optopt = 0;
713 fprintf (stderr, 781 return '?';
714 _
715 ("%s: option `%c%s' doesn't allow an argument\n"),
716 argv[0], argv[optind - 1][0], pfound->name);
717
718 nextchar += strlen (nextchar);
719
720 optopt = pfound->val;
721 return '?';
722 }
723 }
724 else if (pfound->has_arg == 1)
725 {
726 if (optind < argc)
727 optarg = argv[optind++];
728 else
729 {
730 if (opterr)
731 fprintf (stderr,
732 _("%s: option `%s' requires an argument\n"),
733 argv[0], argv[optind - 1]);
734 nextchar += strlen (nextchar);
735 optopt = pfound->val;
736 return optstring[0] == ':' ? ':' : '?';
737 }
738 }
739 nextchar += strlen (nextchar);
740 if (longind != NULL)
741 *longind = option_index;
742 if (pfound->flag)
743 {
744 *(pfound->flag) = pfound->val;
745 return 0;
746 }
747 return pfound->val;
748 }
749
750 /* Can't find it as a long option. If this is not getopt_long_only,
751 or the option starts with '--' or is not a valid short
752 option, then it's an error.
753 Otherwise interpret it as a short option. */
754 if (!long_only || argv[optind][1] == '-'
755 || my_index (optstring, *nextchar) == NULL)
756 {
757 if (opterr)
758 {
759 if (argv[optind][1] == '-')
760 /* --option */
761 fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
762 argv[0], nextchar);
763 else
764 /* +option or -option */
765 fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
766 argv[0], argv[optind][0], nextchar);
767 }
768 nextchar = (char *) "";
769 optind++;
770 optopt = 0;
771 return '?';
772 }
773 } 782 }
783 }
774 784
775 /* Look at and handle the next short option-character. */ 785 /* Look at and handle the next short option-character. */
776 786
@@ -782,205 +792,207 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
782 if (*nextchar == '\0') 792 if (*nextchar == '\0')
783 ++optind; 793 ++optind;
784 794
785 if (temp == NULL || c == ':') 795 if ((temp == NULL) || (c == ':'))
796 {
797 if (opterr)
786 { 798 {
787 if (opterr) 799 if (posixly_correct)
788 { 800 /* 1003.2 specifies the format of this message. */
789 if (posixly_correct) 801 fprintf (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c);
790 /* 1003.2 specifies the format of this message. */ 802 else
791 fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); 803 fprintf (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c);
792 else
793 fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
794 }
795 optopt = c;
796 return '?';
797 } 804 }
805 optopt = c;
806 return '?';
807 }
798 /* Convenience. Treat POSIX -W foo same as long option --foo */ 808 /* Convenience. Treat POSIX -W foo same as long option --foo */
799 if (temp[0] == 'W' && temp[1] == ';') 809 if ((temp[0] == 'W') && (temp[1] == ';'))
810 {
811 char *nameend;
812 const struct option *p;
813 const struct option *pfound = NULL;
814 int exact = 0;
815 int ambig = 0;
816 int indfound = 0;
817 int option_index;
818
819 /* This is an option that requires an argument. */
820 if (*nextchar != '\0')
821 {
822 optarg = nextchar;
823 /* If we end this ARGV-element by taking the rest as an arg,
824 we must advance to the next element now. */
825 optind++;
826 }
827 else if (optind == argc)
828 {
829 if (opterr)
830 {
831 /* 1003.2 specifies the format of this message. */
832 fprintf (stderr, _ ("%s: option requires an argument -- %c\n"),
833 argv[0], c);
834 }
835 optopt = c;
836 if (optstring[0] == ':')
837 c = ':';
838 else
839 c = '?';
840 return c;
841 }
842 else
843 /* We already incremented `optind' once;
844 increment it again when taking next ARGV-elt as argument. */
845 optarg = argv[optind++];
846
847 /* optarg is now the argument, see if it's in the
848 table of longopts. */
849
850 for (nextchar = nameend = optarg; *nameend && *nameend != '=';
851 nameend++)
852 /* Do nothing. */;
853
854 /* Test all long options for either exact match
855 or abbreviated matches. */
856 for (p = longopts, option_index = 0; p->name; p++, option_index++)
857 if (! strncmp (p->name, nextchar, nameend - nextchar))
858 {
859 if ((unsigned int) (nameend - nextchar) == strlen (p->name))
860 {
861 /* Exact match found. */
862 pfound = p;
863 indfound = option_index;
864 exact = 1;
865 break;
866 }
867 else if (pfound == NULL)
868 {
869 /* First nonexact match found. */
870 pfound = p;
871 indfound = option_index;
872 }
873 else
874 /* Second or later nonexact match found. */
875 ambig = 1;
876 }
877 if (ambig && ! exact)
878 {
879 if (opterr)
880 fprintf (stderr, _ ("%s: option `-W %s' is ambiguous\n"),
881 argv[0], argv[optind]);
882 nextchar += strlen (nextchar);
883 optind++;
884 return '?';
885 }
886 if (pfound != NULL)
800 { 887 {
801 char *nameend; 888 option_index = indfound;
802 const struct option *p; 889 if (*nameend)
803 const struct option *pfound = NULL; 890 {
804 int exact = 0; 891 /* Don't test has_arg with >, because some C compilers don't
805 int ambig = 0; 892 allow it to be used on enums. */
806 int indfound = 0; 893 if (pfound->has_arg)
807 int option_index; 894 optarg = nameend + 1;
808 895 else
809 /* This is an option that requires an argument. */ 896 {
810 if (*nextchar != '\0') 897 if (opterr)
811 { 898 fprintf (stderr, _ (
812 optarg = nextchar; 899 "\
813 /* If we end this ARGV-element by taking the rest as an arg,
814 we must advance to the next element now. */
815 optind++;
816 }
817 else if (optind == argc)
818 {
819 if (opterr)
820 {
821 /* 1003.2 specifies the format of this message. */
822 fprintf (stderr, _("%s: option requires an argument -- %c\n"),
823 argv[0], c);
824 }
825 optopt = c;
826 if (optstring[0] == ':')
827 c = ':';
828 else
829 c = '?';
830 return c;
831 }
832 else
833 /* We already incremented `optind' once;
834 increment it again when taking next ARGV-elt as argument. */
835 optarg = argv[optind++];
836
837 /* optarg is now the argument, see if it's in the
838 table of longopts. */
839
840 for (nextchar = nameend = optarg; *nameend && *nameend != '=';
841 nameend++)
842 /* Do nothing. */ ;
843
844 /* Test all long options for either exact match
845 or abbreviated matches. */
846 for (p = longopts, option_index = 0; p->name; p++, option_index++)
847 if (!strncmp (p->name, nextchar, nameend - nextchar))
848 {
849 if ((unsigned int) (nameend - nextchar) == strlen (p->name))
850 {
851 /* Exact match found. */
852 pfound = p;
853 indfound = option_index;
854 exact = 1;
855 break;
856 }
857 else if (pfound == NULL)
858 {
859 /* First nonexact match found. */
860 pfound = p;
861 indfound = option_index;
862 }
863 else
864 /* Second or later nonexact match found. */
865 ambig = 1;
866 }
867 if (ambig && !exact)
868 {
869 if (opterr)
870 fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
871 argv[0], argv[optind]);
872 nextchar += strlen (nextchar);
873 optind++;
874 return '?';
875 }
876 if (pfound != NULL)
877 {
878 option_index = indfound;
879 if (*nameend)
880 {
881 /* Don't test has_arg with >, because some C compilers don't
882 allow it to be used on enums. */
883 if (pfound->has_arg)
884 optarg = nameend + 1;
885 else
886 {
887 if (opterr)
888 fprintf (stderr, _("\
889%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); 900%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name);
890 901
891 nextchar += strlen (nextchar); 902 nextchar += strlen (nextchar);
892 return '?'; 903 return '?';
893 } 904 }
894 } 905 }
895 else if (pfound->has_arg == 1) 906 else if (pfound->has_arg == 1)
896 { 907 {
897 if (optind < argc) 908 if (optind < argc)
898 optarg = argv[optind++]; 909 optarg = argv[optind++];
899 else 910 else
900 { 911 {
901 if (opterr) 912 if (opterr)
902 fprintf (stderr, 913 fprintf (stderr,
903 _("%s: option `%s' requires an argument\n"), 914 _ ("%s: option `%s' requires an argument\n"),
904 argv[0], argv[optind - 1]); 915 argv[0], argv[optind - 1]);
905 nextchar += strlen (nextchar); 916 nextchar += strlen (nextchar);
906 return optstring[0] == ':' ? ':' : '?'; 917 return optstring[0] == ':' ? ':' : '?';
907 } 918 }
908 } 919 }
909 nextchar += strlen (nextchar); 920 nextchar += strlen (nextchar);
910 if (longind != NULL) 921 if (longind != NULL)
911 *longind = option_index; 922 *longind = option_index;
912 if (pfound->flag) 923 if (pfound->flag)
913 { 924 {
914 *(pfound->flag) = pfound->val; 925 *(pfound->flag) = pfound->val;
915 return 0; 926 return 0;
916 } 927 }
917 return pfound->val; 928 return pfound->val;
918 }
919 nextchar = NULL;
920 return 'W'; /* Let the application handle it. */
921 } 929 }
930 nextchar = NULL;
931 return 'W'; /* Let the application handle it. */
932 }
922 if (temp[1] == ':') 933 if (temp[1] == ':')
934 {
935 if (temp[2] == ':')
936 {
937 /* This is an option that accepts an argument optionally. */
938 if (*nextchar != '\0')
939 {
940 optarg = nextchar;
941 optind++;
942 }
943 else
944 optarg = NULL;
945 nextchar = NULL;
946 }
947 else
923 { 948 {
924 if (temp[2] == ':') 949 /* This is an option that requires an argument. */
925 { 950 if (*nextchar != '\0')
926 /* This is an option that accepts an argument optionally. */ 951 {
927 if (*nextchar != '\0') 952 optarg = nextchar;
928 { 953 /* If we end this ARGV-element by taking the rest as an arg,
929 optarg = nextchar; 954 we must advance to the next element now. */
930 optind++; 955 optind++;
931 } 956 }
932 else 957 else if (optind == argc)
933 optarg = NULL; 958 {
934 nextchar = NULL; 959 if (opterr)
935 } 960 {
936 else 961 /* 1003.2 specifies the format of this message. */
937 { 962 fprintf (stderr,
938 /* This is an option that requires an argument. */ 963 _ ("%s: option requires an argument -- %c\n"),
939 if (*nextchar != '\0') 964 argv[0], c);
940 { 965 }
941 optarg = nextchar; 966 optopt = c;
942 /* If we end this ARGV-element by taking the rest as an arg, 967 if (optstring[0] == ':')
943 we must advance to the next element now. */ 968 c = ':';
944 optind++; 969 else
945 } 970 c = '?';
946 else if (optind == argc) 971 }
947 { 972 else
948 if (opterr) 973 /* We already incremented `optind' once;
949 { 974 increment it again when taking next ARGV-elt as argument. */
950 /* 1003.2 specifies the format of this message. */ 975 optarg = argv[optind++];
951 fprintf (stderr, 976 nextchar = NULL;
952 _("%s: option requires an argument -- %c\n"),
953 argv[0], c);
954 }
955 optopt = c;
956 if (optstring[0] == ':')
957 c = ':';
958 else
959 c = '?';
960 }
961 else
962 /* We already incremented `optind' once;
963 increment it again when taking next ARGV-elt as argument. */
964 optarg = argv[optind++];
965 nextchar = NULL;
966 }
967 } 977 }
978 }
968 return c; 979 return c;
969 } 980 }
970} 981}
971 982
972int 983int
973getopt (argc, argv, optstring) 984getopt (argc, argv, optstring)
974 int argc; 985int argc;
975 char *const *argv; 986
976 const char *optstring; 987char *const *argv;
988const char *optstring;
977{ 989{
978 return _getopt_internal (argc, argv, optstring, 990 return _getopt_internal (argc, argv, optstring,
979 (const struct option *) 0, (int *) 0, 0); 991 (const struct option *) 0, (int *) 0, 0);
980} 992}
981 993
982#endif /* Not ELIDE_CODE. */ 994#endif /* Not ELIDE_CODE. */
983 995
984#ifdef TEST 996#ifdef TEST
985 997
986/* Compile with -DTEST to make an executable for use in testing 998/* Compile with -DTEST to make an executable for use in testing
@@ -988,65 +1000,66 @@ getopt (argc, argv, optstring)
988 1000
989int 1001int
990main (argc, argv) 1002main (argc, argv)
991 int argc; 1003int argc;
992 char **argv; 1004
1005char **argv;
993{ 1006{
994 int c; 1007 int c;
995 int digit_optind = 0; 1008 int digit_optind = 0;
996 1009
997 while (1) 1010 while (1)
1011 {
1012 int this_option_optind = optind ? optind : 1;
1013
1014 c = getopt (argc, argv, "abc:d:0123456789");
1015 if (c == -1)
1016 break;
1017
1018 switch (c)
998 { 1019 {
999 int this_option_optind = optind ? optind : 1; 1020 case '0':
1000 1021 case '1':
1001 c = getopt (argc, argv, "abc:d:0123456789"); 1022 case '2':
1002 if (c == -1) 1023 case '3':
1003 break; 1024 case '4':
1004 1025 case '5':
1005 switch (c) 1026 case '6':
1006 { 1027 case '7':
1007 case '0': 1028 case '8':
1008 case '1': 1029 case '9':
1009 case '2': 1030 if ((digit_optind != 0) && (digit_optind != this_option_optind) )
1010 case '3': 1031 printf ("digits occur in two different argv-elements.\n");
1011 case '4': 1032 digit_optind = this_option_optind;
1012 case '5': 1033 printf ("option %c\n", c);
1013 case '6': 1034 break;
1014 case '7': 1035
1015 case '8': 1036 case 'a':
1016 case '9': 1037 printf ("option a\n");
1017 if (digit_optind != 0 && digit_optind != this_option_optind) 1038 break;
1018 printf ("digits occur in two different argv-elements.\n"); 1039
1019 digit_optind = this_option_optind; 1040 case 'b':
1020 printf ("option %c\n", c); 1041 printf ("option b\n");
1021 break; 1042 break;
1022 1043
1023 case 'a': 1044 case 'c':
1024 printf ("option a\n"); 1045 printf ("option c with value `%s'\n", optarg);
1025 break; 1046 break;
1026 1047
1027 case 'b': 1048 case '?':
1028 printf ("option b\n"); 1049 break;
1029 break; 1050
1030 1051 default:
1031 case 'c': 1052 printf ("?? getopt returned character code 0%o ??\n", c);
1032 printf ("option c with value `%s'\n", optarg);
1033 break;
1034
1035 case '?':
1036 break;
1037
1038 default:
1039 printf ("?? getopt returned character code 0%o ??\n", c);
1040 }
1041 } 1053 }
1054 }
1042 1055
1043 if (optind < argc) 1056 if (optind < argc)
1044 { 1057 {
1045 printf ("non-option ARGV-elements: "); 1058 printf ("non-option ARGV-elements: ");
1046 while (optind < argc) 1059 while (optind < argc)
1047 printf ("%s ", argv[optind++]); 1060 printf ("%s ", argv[optind++]);
1048 printf ("\n"); 1061 printf ("\n");
1049 } 1062 }
1050 1063
1051 exit (0); 1064 exit (0);
1052} 1065}
diff --git a/src/main/getopt.h b/src/main/getopt.h
index d50c90e..89fd8eb 100644
--- a/src/main/getopt.h
+++ b/src/main/getopt.h
@@ -24,7 +24,7 @@ USA. */
24 24
25#include "config.h" 25#include "config.h"
26 26
27#ifdef __cplusplus 27#ifdef __cplusplus
28extern "C" { 28extern "C" {
29#endif 29#endif
30 30
@@ -67,7 +67,7 @@ extern int optopt;
67 The field `has_arg' is: 67 The field `has_arg' is:
68 no_argument (or 0) if the option does not take an argument, 68 no_argument (or 0) if the option does not take an argument,
69 required_argument (or 1) if the option requires an argument, 69 required_argument (or 1) if the option requires an argument,
70 optional_argument (or 2) if the option takes an optional argument. 70 optional_argument (or 2) if the option takes an optional argument.
71 71
72 If the field `flag' is not NULL, it points to a variable that is set 72 If the field `flag' is not NULL, it points to a variable that is set
73 to the value given in the field `val' when the option is found, but 73 to the value given in the field `val' when the option is found, but
@@ -96,9 +96,9 @@ struct option
96 96
97/* Names for the values of the `has_arg' field of `struct option'. */ 97/* Names for the values of the `has_arg' field of `struct option'. */
98 98
99#define no_argument 0 99#define no_argument 0
100#define required_argument 1 100#define required_argument 1
101#define optional_argument 2 101#define optional_argument 2
102 102
103#if defined (__STDC__) && __STDC__ 103#if defined (__STDC__) && __STDC__
104#ifdef __GNU_LIBRARY__ 104#ifdef __GNU_LIBRARY__
@@ -106,29 +106,36 @@ struct option
106 differences in the consts, in stdlib.h. To avoid compilation 106 differences in the consts, in stdlib.h. To avoid compilation
107 errors, only prototype getopt for the GNU C library. */ 107 errors, only prototype getopt for the GNU C library. */
108extern int getopt (int argc, char *const *argv, const char *shortopts); 108extern int getopt (int argc, char *const *argv, const char *shortopts);
109
109#else /* not __GNU_LIBRARY__ */ 110#else /* not __GNU_LIBRARY__ */
110extern int getopt (); 111extern int getopt ();
112
111#endif /* __GNU_LIBRARY__ */ 113#endif /* __GNU_LIBRARY__ */
112extern int getopt_long (int argc, char *const *argv, const char *shortopts, 114extern int getopt_long (int argc, char *const *argv, const char *shortopts,
113 const struct option *longopts, int *longind); 115 const struct option *longopts, int *longind);
116
114extern int getopt_long_only (int argc, char *const *argv, 117extern int getopt_long_only (int argc, char *const *argv,
115 const char *shortopts, 118 const char *shortopts,
116 const struct option *longopts, int *longind); 119 const struct option *longopts, int *longind);
117 120
118/* Internal only. Users should not call this directly. */ 121/* Internal only. Users should not call this directly. */
119extern int _getopt_internal (int argc, char *const *argv, 122extern int _getopt_internal (int argc, char *const *argv,
120 const char *shortopts, 123 const char *shortopts,
121 const struct option *longopts, int *longind, 124 const struct option *longopts, int *longind,
122 int long_only); 125 int long_only);
126
123#else /* not __STDC__ */ 127#else /* not __STDC__ */
124extern int getopt (); 128extern int getopt ();
129
125extern int getopt_long (); 130extern int getopt_long ();
131
126extern int getopt_long_only (); 132extern int getopt_long_only ();
127 133
128extern int _getopt_internal (); 134extern int _getopt_internal ();
135
129#endif /* __STDC__ */ 136#endif /* __STDC__ */
130 137
131#ifdef __cplusplus 138#ifdef __cplusplus
132} 139}
133#endif 140#endif
134 141
diff --git a/src/main/getopt1.c b/src/main/getopt1.c
index 6409986..d089fd4 100644
--- a/src/main/getopt1.c
+++ b/src/main/getopt1.c
@@ -21,7 +21,7 @@ USA. */
21#include "config.h" 21#include "config.h"
22#include "getopt.h" 22#include "getopt.h"
23 23
24#if !defined (__STDC__) || !__STDC__ 24#if ! defined (__STDC__) || ! __STDC__
25/* This is a separate conditional since some stdc systems 25/* This is a separate conditional since some stdc systems
26 reject `defined (const)'. */ 26 reject `defined (const)'. */
27#ifndef const 27#ifndef const
@@ -40,7 +40,7 @@ USA. */
40 it is simpler to just do this in the source for each such file. */ 40 it is simpler to just do this in the source for each such file. */
41 41
42#define GETOPT_INTERFACE_VERSION 2 42#define GETOPT_INTERFACE_VERSION 2
43#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 43#if ! defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
44#include <gnu-versions.h> 44#include <gnu-versions.h>
45#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION 45#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
46#define ELIDE_CODE 46#define ELIDE_CODE
@@ -56,17 +56,18 @@ USA. */
56#include <stdlib.h> 56#include <stdlib.h>
57#endif 57#endif
58 58
59#ifndef NULL 59#ifndef NULL
60#define NULL 0 60#define NULL 0
61#endif 61#endif
62 62
63int 63int
64getopt_long (argc, argv, options, long_options, opt_index) 64getopt_long (argc, argv, options, long_options, opt_index)
65 int argc; 65int argc;
66 char *const *argv; 66
67 const char *options; 67char *const *argv;
68 const struct option *long_options; 68const char *options;
69 int *opt_index; 69const struct option *long_options;
70int *opt_index;
70{ 71{
71 return _getopt_internal (argc, argv, options, long_options, opt_index, 0); 72 return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
72} 73}
@@ -78,105 +79,107 @@ getopt_long (argc, argv, options, long_options, opt_index)
78 79
79int 80int
80getopt_long_only (argc, argv, options, long_options, opt_index) 81getopt_long_only (argc, argv, options, long_options, opt_index)
81 int argc; 82int argc;
82 char *const *argv; 83
83 const char *options; 84char *const *argv;
84 const struct option *long_options; 85const char *options;
85 int *opt_index; 86const struct option *long_options;
87int *opt_index;
86{ 88{
87 return _getopt_internal (argc, argv, options, long_options, opt_index, 1); 89 return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
88} 90}
89 91
90 92
91#endif /* Not ELIDE_CODE. */ 93#endif /* Not ELIDE_CODE. */
92 94
93#ifdef TEST 95#ifdef TEST
94 96
95#include <stdio.h> 97#include <stdio.h>
96 98
97int 99int
98main (argc, argv) 100main (argc, argv)
99 int argc; 101int argc;
100 char **argv; 102
103char **argv;
101{ 104{
102 int c; 105 int c;
103 int digit_optind = 0; 106 int digit_optind = 0;
104 107
105 while (1) 108 while (1)
109 {
110 int this_option_optind = optind ? optind : 1;
111 int option_index = 0;
112 static struct option long_options[] = {
113 {"add", 1, 0, 0},
114 {"append", 0, 0, 0},
115 {"delete", 1, 0, 0},
116 {"verbose", 0, 0, 0},
117 {"create", 0, 0, 0},
118 {"file", 1, 0, 0},
119 {0, 0, 0, 0}
120 };
121
122 c = getopt_long (argc, argv, "abc:d:0123456789",
123 long_options, &option_index);
124 if (c == -1)
125 break;
126
127 switch (c)
106 { 128 {
107 int this_option_optind = optind ? optind : 1; 129 case 0:
108 int option_index = 0; 130 printf ("option %s", long_options[option_index].name);
109 static struct option long_options[] = { 131 if (optarg)
110 {"add", 1, 0, 0}, 132 printf (" with arg %s", optarg);
111 {"append", 0, 0, 0}, 133 printf ("\n");
112 {"delete", 1, 0, 0}, 134 break;
113 {"verbose", 0, 0, 0}, 135
114 {"create", 0, 0, 0}, 136 case '0':
115 {"file", 1, 0, 0}, 137 case '1':
116 {0, 0, 0, 0} 138 case '2':
117 }; 139 case '3':
118 140 case '4':
119 c = getopt_long (argc, argv, "abc:d:0123456789", 141 case '5':
120 long_options, &option_index); 142 case '6':
121 if (c == -1) 143 case '7':
122 break; 144 case '8':
123 145 case '9':
124 switch (c) 146 if ((digit_optind != 0) && (digit_optind != this_option_optind) )
125 { 147 printf ("digits occur in two different argv-elements.\n");
126 case 0: 148 digit_optind = this_option_optind;
127 printf ("option %s", long_options[option_index].name); 149 printf ("option %c\n", c);
128 if (optarg) 150 break;
129 printf (" with arg %s", optarg); 151
130 printf ("\n"); 152 case 'a':
131 break; 153 printf ("option a\n");
132 154 break;
133 case '0': 155
134 case '1': 156 case 'b':
135 case '2': 157 printf ("option b\n");
136 case '3': 158 break;
137 case '4': 159
138 case '5': 160 case 'c':
139 case '6': 161 printf ("option c with value `%s'\n", optarg);
140 case '7': 162 break;
141 case '8': 163
142 case '9': 164 case 'd':
143 if (digit_optind != 0 && digit_optind != this_option_optind) 165 printf ("option d with value `%s'\n", optarg);
144 printf ("digits occur in two different argv-elements.\n"); 166 break;
145 digit_optind = this_option_optind; 167
146 printf ("option %c\n", c); 168 case '?':
147 break; 169 break;
148 170
149 case 'a': 171 default:
150 printf ("option a\n"); 172 printf ("?? getopt returned character code 0%o ??\n", c);
151 break;
152
153 case 'b':
154 printf ("option b\n");
155 break;
156
157 case 'c':
158 printf ("option c with value `%s'\n", optarg);
159 break;
160
161 case 'd':
162 printf ("option d with value `%s'\n", optarg);
163 break;
164
165 case '?':
166 break;
167
168 default:
169 printf ("?? getopt returned character code 0%o ??\n", c);
170 }
171 } 173 }
174 }
172 175
173 if (optind < argc) 176 if (optind < argc)
174 { 177 {
175 printf ("non-option ARGV-elements: "); 178 printf ("non-option ARGV-elements: ");
176 while (optind < argc) 179 while (optind < argc)
177 printf ("%s ", argv[optind++]); 180 printf ("%s ", argv[optind++]);
178 printf ("\n"); 181 printf ("\n");
179 } 182 }
180 183
181 exit (0); 184 exit (0);
182} 185}
diff --git a/src/main/iconv.c b/src/main/iconv.c
index 3f95d44..7daa017 100644
--- a/src/main/iconv.c
+++ b/src/main/iconv.c
@@ -33,10 +33,10 @@
33 * @param inSize number of bytes in 'in' 33 * @param inSize number of bytes in 'in'
34 * @return NULL on error, otherwise the converted string (to be free'd by caller) 34 * @return NULL on error, otherwise the converted string (to be free'd by caller)
35 */ 35 */
36static char * 36static char *
37iconv_helper (iconv_t cd, 37iconv_helper (iconv_t cd,
38 const char *in, 38 const char *in,
39 size_t inSize) 39 size_t inSize)
40{ 40{
41#if HAVE_ICONV 41#if HAVE_ICONV
42 char *buf; 42 char *buf;
@@ -57,24 +57,25 @@ iconv_helper (iconv_t cd,
57 ibuf = buf; 57 ibuf = buf;
58 memset (buf, 0, outSize); 58 memset (buf, 0, outSize);
59 if (iconv (cd, 59 if (iconv (cd,
60 (char**) &in, 60 (char**) &in,
61 &inSize, 61 &inSize,
62 &ibuf, 62 &ibuf,
63 &outLeft) == SIZE_MAX) 63 &outLeft) == SIZE_MAX)
64 { 64 {
65 /* conversion failed */ 65 /* conversion failed */
66 free (buf); 66 free (buf);
67 return strdup (i); 67 return strdup (i);
68 } 68 }
69 return buf; 69 return buf;
70#else 70#else
71 /* good luck, just copying string... */ 71 /* good luck, just copying string... */
72 char *buf; 72 char *buf;
73 73
74 buf = malloc (inSize + 1); 74 buf = malloc (inSize + 1);
75 memcpy (buf, in, inSize); 75 memcpy (buf, in, inSize);
76 buf[inSize] = '\0'; 76 buf[inSize] = '\0';
77#endif 77#endif
78} 78}
79 79
80
80/* end of iconv.c */ 81/* end of iconv.c */
diff --git a/src/main/test2_extractor.c b/src/main/test2_extractor.c
index 4d55dc3..a2c1d53 100644
--- a/src/main/test2_extractor.c
+++ b/src/main/test2_extractor.c
@@ -36,7 +36,6 @@
36#include <unistd.h> 36#include <unistd.h>
37#include <stdlib.h> 37#include <stdlib.h>
38 38
39
40 39
41/** 40/**
42 * Signature of the extract method that each plugin 41 * Signature of the extract method that each plugin
@@ -52,77 +51,78 @@ EXTRACTOR_test2_extract_method (struct EXTRACTOR_ExtractContext *ec)
52 if ((NULL == ec->config) || (0 != strcmp (ec->config, "test2"))) 51 if ((NULL == ec->config) || (0 != strcmp (ec->config, "test2")))
53 return; /* only run in test mode */ 52 return; /* only run in test mode */
54 if (4 != ec->read (ec->cls, &dp, 4)) 53 if (4 != ec->read (ec->cls, &dp, 4))
55 { 54 {
56 fprintf (stderr, "Reading at offset 0 failed\n"); 55 fprintf (stderr, "Reading at offset 0 failed\n");
57 ABORT (); 56 ABORT ();
58 } 57 }
59 if (0 != strncmp ("test", dp, 4)) 58 if (0 != strncmp ("test", dp, 4))
60 { 59 {
61 fprintf (stderr, "Unexpected data at offset 0\n"); 60 fprintf (stderr, "Unexpected data at offset 0\n");
62 ABORT (); 61 ABORT ();
63 } 62 }
64 if ( (1024 * 150 != ec->get_size (ec->cls)) && 63 if ( (1024 * 150 != ec->get_size (ec->cls)) &&
65 (UINT64_MAX != ec->get_size (ec->cls)) ) 64 (UINT64_MAX != ec->get_size (ec->cls)) )
66 { 65 {
67 fprintf (stderr, "Unexpected file size returned (expected 150k)\n"); 66 fprintf (stderr, "Unexpected file size returned (expected 150k)\n");
68 ABORT (); 67 ABORT ();
69 } 68 }
70 if (1024 * 100 + 4 != ec->seek (ec->cls, 1024 * 100 + 4, SEEK_SET)) 69 if (1024 * 100 + 4 != ec->seek (ec->cls, 1024 * 100 + 4, SEEK_SET))
71 { 70 {
72 fprintf (stderr, "Failure to seek (SEEK_SET)\n"); 71 fprintf (stderr, "Failure to seek (SEEK_SET)\n");
73 ABORT (); 72 ABORT ();
74 } 73 }
75 if (1 != ec->read (ec->cls, &dp, 1)) 74 if (1 != ec->read (ec->cls, &dp, 1))
76 { 75 {
77 fprintf (stderr, "Failure to read at 100k + 4\n"); 76 fprintf (stderr, "Failure to read at 100k + 4\n");
78 ABORT (); 77 ABORT ();
79 } 78 }
80 if ((1024 * 100 + 4) % 256 != * (unsigned char *) dp) 79 if ((1024 * 100 + 4) % 256 != *(unsigned char *) dp)
81 { 80 {
82 fprintf (stderr, "Unexpected data at offset 100k + 4\n"); 81 fprintf (stderr, "Unexpected data at offset 100k + 4\n");
83 ABORT (); 82 ABORT ();
84 } 83 }
85 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) != 84 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) !=
86 ec->seek (ec->cls, - (1024 * 50 + 7), SEEK_CUR)) 85 ec->seek (ec->cls, -(1024 * 50 + 7), SEEK_CUR))
87 { 86 {
88 fprintf (stderr, "Failure to seek (SEEK_SET)\n"); 87 fprintf (stderr, "Failure to seek (SEEK_SET)\n");
89 ABORT (); 88 ABORT ();
90 } 89 }
91 if (1 != ec->read (ec->cls, &dp, 1)) 90 if (1 != ec->read (ec->cls, &dp, 1))
92 { 91 {
93 fprintf (stderr, "Failure to read at 50k - 3\n"); 92 fprintf (stderr, "Failure to read at 50k - 3\n");
94 ABORT (); 93 ABORT ();
95 } 94 }
96 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) % 256 != * (unsigned char *) dp) 95 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) % 256 != *(unsigned char *) dp)
97 { 96 {
98 fprintf (stderr, "Unexpected data at offset 100k - 3\n"); 97 fprintf (stderr, "Unexpected data at offset 100k - 3\n");
99 ABORT (); 98 ABORT ();
100 } 99 }
101 if (1024 * 150 != ec->seek (ec->cls, 0, SEEK_END)) 100 if (1024 * 150 != ec->seek (ec->cls, 0, SEEK_END))
102 { 101 {
103 fprintf (stderr, "Failure to seek (SEEK_END)\n"); 102 fprintf (stderr, "Failure to seek (SEEK_END)\n");
104 ABORT (); 103 ABORT ();
105 } 104 }
106 if (0 != ec->read (ec->cls, &dp, 1)) 105 if (0 != ec->read (ec->cls, &dp, 1))
107 { 106 {
108 fprintf (stderr, "Failed to receive EOF at 150k\n"); 107 fprintf (stderr, "Failed to receive EOF at 150k\n");
109 ABORT (); 108 ABORT ();
110 } 109 }
111 if (1024 * 150 - 2 != ec->seek (ec->cls, -2, SEEK_END)) 110 if (1024 * 150 - 2 != ec->seek (ec->cls, -2, SEEK_END))
112 { 111 {
113 fprintf (stderr, "Failure to seek (SEEK_END - 2)\n"); 112 fprintf (stderr, "Failure to seek (SEEK_END - 2)\n");
114 ABORT (); 113 ABORT ();
115 } 114 }
116 if (1 != ec->read (ec->cls, &dp, 1)) 115 if (1 != ec->read (ec->cls, &dp, 1))
117 { 116 {
118 fprintf (stderr, "Failure to read at 150k - 3\n"); 117 fprintf (stderr, "Failure to read at 150k - 3\n");
119 ABORT (); 118 ABORT ();
120 } 119 }
121 if ((1024 * 150 - 2) % 256 != * (unsigned char *) dp) 120 if ((1024 * 150 - 2) % 256 != *(unsigned char *) dp)
122 { 121 {
123 fprintf (stderr, "Unexpected data at offset 150k - 3\n"); 122 fprintf (stderr, "Unexpected data at offset 150k - 3\n");
124 ABORT (); 123 ABORT ();
125 } 124 }
126} 125}
127 126
127
128/* end of test2_extractor.c */ 128/* end of test2_extractor.c */
diff --git a/src/main/test_bzip2.c b/src/main/test_bzip2.c
index 37c9aed..598e913 100644
--- a/src/main/test_bzip2.c
+++ b/src/main/test_bzip2.c
@@ -46,74 +46,74 @@ static int ret = 2;
46 * @param data hello world or good bye 46 * @param data hello world or good bye
47 * @param data_len number of bytes in data 47 * @param data_len number of bytes in data
48 * @return 0 on hello world, 1 on goodbye 48 * @return 0 on hello world, 1 on goodbye
49 */ 49 */
50static int 50static int
51process_replies (void *cls, 51process_replies (void *cls,
52 const char *plugin_name, 52 const char *plugin_name,
53 enum EXTRACTOR_MetaType type, 53 enum EXTRACTOR_MetaType type,
54 enum EXTRACTOR_MetaFormat format, 54 enum EXTRACTOR_MetaFormat format,
55 const char *data_mime_type, 55 const char *data_mime_type,
56 const char *data, 56 const char *data,
57 size_t data_len) 57 size_t data_len)
58{ 58{
59 if (0 != strcmp (cls, 59 if (0 != strcmp (cls,
60 "main-cls")) 60 "main-cls"))
61 { 61 {
62 fprintf (stderr, "closure invalid\n"); 62 fprintf (stderr, "closure invalid\n");
63 ret = 3; 63 ret = 3;
64 return 1; 64 return 1;
65 } 65 }
66 if (0 != strcmp (plugin_name, 66 if (0 != strcmp (plugin_name,
67 "test")) 67 "test"))
68 { 68 {
69 fprintf (stderr, "plugin name invalid\n"); 69 fprintf (stderr, "plugin name invalid\n");
70 ret = 4; 70 ret = 4;
71 return 1; 71 return 1;
72 } 72 }
73 if (EXTRACTOR_METATYPE_COMMENT != type) 73 if (EXTRACTOR_METATYPE_COMMENT != type)
74 { 74 {
75 fprintf (stderr, "type invalid\n"); 75 fprintf (stderr, "type invalid\n");
76 ret = 5; 76 ret = 5;
77 return 1; 77 return 1;
78 } 78 }
79 if (EXTRACTOR_METAFORMAT_UTF8 != format) 79 if (EXTRACTOR_METAFORMAT_UTF8 != format)
80 { 80 {
81 fprintf (stderr, "format invalid\n"); 81 fprintf (stderr, "format invalid\n");
82 ret = 6; 82 ret = 6;
83 return 1; 83 return 1;
84 } 84 }
85 if ( (NULL == data_mime_type) || 85 if ( (NULL == data_mime_type) ||
86 (0 != strcmp ("<no mime>", 86 (0 != strcmp ("<no mime>",
87 data_mime_type) ) ) 87 data_mime_type) ) )
88 { 88 {
89 fprintf (stderr, "bad mime type\n"); 89 fprintf (stderr, "bad mime type\n");
90 ret = 7; 90 ret = 7;
91 return 1; 91 return 1;
92 } 92 }
93 if ( (2 == ret) && 93 if ( (2 == ret) &&
94 (data_len == strlen (HLO) + 1) && 94 (data_len == strlen (HLO) + 1) &&
95 (0 == strncmp (data, 95 (0 == strncmp (data,
96 HLO, 96 HLO,
97 strlen (HLO))) ) 97 strlen (HLO))) )
98 { 98 {
99#if 0 99#if 0
100 fprintf (stderr, "Received '%s'\n", HLO); 100 fprintf (stderr, "Received '%s'\n", HLO);
101#endif 101#endif
102 ret = 1; 102 ret = 1;
103 return 0; 103 return 0;
104 } 104 }
105 if ( (1 == ret) && 105 if ( (1 == ret) &&
106 (data_len == strlen (GOB) + 1) && 106 (data_len == strlen (GOB) + 1) &&
107 (0 == strncmp (data, 107 (0 == strncmp (data,
108 GOB, 108 GOB,
109 strlen (GOB))) ) 109 strlen (GOB))) )
110 { 110 {
111#if 0 111#if 0
112 fprintf (stderr, "Received '%s'\n", GOB); 112 fprintf (stderr, "Received '%s'\n", GOB);
113#endif 113#endif
114 ret = 0; 114 ret = 0;
115 return 1; 115 return 1;
116 } 116 }
117 fprintf (stderr, "Invalid meta data\n"); 117 fprintf (stderr, "Invalid meta data\n");
118 ret = 8; 118 ret = 8;
119 return 1; 119 return 1;
@@ -132,23 +132,25 @@ main (int argc, char *argv[])
132{ 132{
133 struct EXTRACTOR_PluginList *pl; 133 struct EXTRACTOR_PluginList *pl;
134 134
135 /* change environment to find 'extractor_test' plugin which is 135 /* change environment to find 'extractor_test' plugin which is
136 not installed but should be in the current directory (or .libs) 136 not installed but should be in the current directory (or .libs)
137 on 'make check' */ 137 on 'make check' */
138 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 138 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
139 fprintf (stderr, 139 fprintf (stderr,
140 "Failed to update my environment, plugin loading may fail: %s\n", 140 "Failed to update my environment, plugin loading may fail: %s\n",
141 strerror (errno)); 141 strerror (errno));
142 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)", 142 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)",
143 EXTRACTOR_OPTION_DEFAULT_POLICY); 143 EXTRACTOR_OPTION_DEFAULT_POLICY);
144 if (NULL == pl) 144 if (NULL == pl)
145 { 145 {
146 fprintf (stderr, "failed to load test plugin\n"); 146 fprintf (stderr, "failed to load test plugin\n");
147 return 1; 147 return 1;
148 } 148 }
149 EXTRACTOR_extract (pl, "test_file.dat.bz2", NULL, 0, &process_replies, "main-cls"); 149 EXTRACTOR_extract (pl, "test_file.dat.bz2", NULL, 0, &process_replies,
150 "main-cls");
150 EXTRACTOR_plugin_remove_all (pl); 151 EXTRACTOR_plugin_remove_all (pl);
151 return ret; 152 return ret;
152} 153}
153 154
155
154/* end of test_bzip2.c */ 156/* end of test_bzip2.c */
diff --git a/src/main/test_extractor.c b/src/main/test_extractor.c
index 8c15fca..dd1376f 100644
--- a/src/main/test_extractor.c
+++ b/src/main/test_extractor.c
@@ -37,7 +37,6 @@
37#include <stdlib.h> 37#include <stdlib.h>
38 38
39 39
40
41/** 40/**
42 * Signature of the extract method that each plugin 41 * Signature of the extract method that each plugin
43 * must provide. 42 * must provide.
@@ -52,94 +51,95 @@ EXTRACTOR_test_extract_method (struct EXTRACTOR_ExtractContext *ec)
52 if ((NULL == ec->config) || (0 != strcmp (ec->config, "test"))) 51 if ((NULL == ec->config) || (0 != strcmp (ec->config, "test")))
53 return; /* only run in test mode */ 52 return; /* only run in test mode */
54 if (4 != ec->read (ec->cls, &dp, 4)) 53 if (4 != ec->read (ec->cls, &dp, 4))
55 { 54 {
56 fprintf (stderr, "Reading at offset 0 failed\n"); 55 fprintf (stderr, "Reading at offset 0 failed\n");
57 ABORT (); 56 ABORT ();
58 } 57 }
59 if (0 != strncmp ("test", dp, 4)) 58 if (0 != strncmp ("test", dp, 4))
60 { 59 {
61 fprintf (stderr, "Unexpected data at offset 0\n"); 60 fprintf (stderr, "Unexpected data at offset 0\n");
62 ABORT (); 61 ABORT ();
63 } 62 }
64 if ( (1024 * 150 != ec->get_size (ec->cls)) && 63 if ( (1024 * 150 != ec->get_size (ec->cls)) &&
65 (UINT64_MAX != ec->get_size (ec->cls)) ) 64 (UINT64_MAX != ec->get_size (ec->cls)) )
66 { 65 {
67 fprintf (stderr, "Unexpected file size returned (expected 150k)\n"); 66 fprintf (stderr, "Unexpected file size returned (expected 150k)\n");
68 ABORT (); 67 ABORT ();
69 } 68 }
70 if (1024 * 100 + 4 != ec->seek (ec->cls, 1024 * 100 + 4, SEEK_SET)) 69 if (1024 * 100 + 4 != ec->seek (ec->cls, 1024 * 100 + 4, SEEK_SET))
71 { 70 {
72 fprintf (stderr, "Failure to seek (SEEK_SET)\n"); 71 fprintf (stderr, "Failure to seek (SEEK_SET)\n");
73 ABORT (); 72 ABORT ();
74 } 73 }
75 if (1 != ec->read (ec->cls, &dp, 1)) 74 if (1 != ec->read (ec->cls, &dp, 1))
76 { 75 {
77 fprintf (stderr, "Failure to read at 100k + 4\n"); 76 fprintf (stderr, "Failure to read at 100k + 4\n");
78 ABORT (); 77 ABORT ();
79 } 78 }
80 if ((1024 * 100 + 4) % 256 != * (unsigned char *) dp) 79 if ((1024 * 100 + 4) % 256 != *(unsigned char *) dp)
81 { 80 {
82 fprintf (stderr, "Unexpected data at offset 100k + 4\n"); 81 fprintf (stderr, "Unexpected data at offset 100k + 4\n");
83 ABORT (); 82 ABORT ();
84 } 83 }
85 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) != 84 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) !=
86 ec->seek (ec->cls, - (1024 * 50 + 7), SEEK_CUR)) 85 ec->seek (ec->cls, -(1024 * 50 + 7), SEEK_CUR))
87 { 86 {
88 fprintf (stderr, "Failure to seek (SEEK_SET)\n"); 87 fprintf (stderr, "Failure to seek (SEEK_SET)\n");
89 ABORT (); 88 ABORT ();
90 } 89 }
91 if (1 != ec->read (ec->cls, &dp, 1)) 90 if (1 != ec->read (ec->cls, &dp, 1))
92 { 91 {
93 fprintf (stderr, "Failure to read at 50k - 3\n"); 92 fprintf (stderr, "Failure to read at 50k - 3\n");
94 ABORT (); 93 ABORT ();
95 } 94 }
96 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) % 256 != * (unsigned char *) dp) 95 if (((1024 * 100 + 4) + 1 - (1024 * 50 + 7)) % 256 != *(unsigned char *) dp)
97 { 96 {
98 fprintf (stderr, "Unexpected data at offset 100k - 3\n"); 97 fprintf (stderr, "Unexpected data at offset 100k - 3\n");
99 ABORT (); 98 ABORT ();
100 } 99 }
101 if (1024 * 150 != ec->seek (ec->cls, 0, SEEK_END)) 100 if (1024 * 150 != ec->seek (ec->cls, 0, SEEK_END))
102 { 101 {
103 fprintf (stderr, "Failure to seek (SEEK_END)\n"); 102 fprintf (stderr, "Failure to seek (SEEK_END)\n");
104 ABORT (); 103 ABORT ();
105 } 104 }
106 if (0 != ec->read (ec->cls, &dp, 1)) 105 if (0 != ec->read (ec->cls, &dp, 1))
107 { 106 {
108 fprintf (stderr, "Failed to receive EOF at 150k\n"); 107 fprintf (stderr, "Failed to receive EOF at 150k\n");
109 ABORT (); 108 ABORT ();
110 } 109 }
111 if (1024 * 150 - 2 != ec->seek (ec->cls, -2, SEEK_END)) 110 if (1024 * 150 - 2 != ec->seek (ec->cls, -2, SEEK_END))
112 { 111 {
113 fprintf (stderr, "Failure to seek (SEEK_END - 2)\n"); 112 fprintf (stderr, "Failure to seek (SEEK_END - 2)\n");
114 ABORT (); 113 ABORT ();
115 } 114 }
116 if (1 != ec->read (ec->cls, &dp, 1)) 115 if (1 != ec->read (ec->cls, &dp, 1))
117 { 116 {
118 fprintf (stderr, "Failure to read at 150k - 3\n"); 117 fprintf (stderr, "Failure to read at 150k - 3\n");
119 ABORT (); 118 ABORT ();
120 } 119 }
121 if ((1024 * 150 - 2) % 256 != * (unsigned char *) dp) 120 if ((1024 * 150 - 2) % 256 != *(unsigned char *) dp)
122 { 121 {
123 fprintf (stderr, "Unexpected data at offset 150k - 3\n"); 122 fprintf (stderr, "Unexpected data at offset 150k - 3\n");
124 ABORT (); 123 ABORT ();
125 } 124 }
126 if (0 != ec->proc (ec->cls, "test", EXTRACTOR_METATYPE_COMMENT, 125 if (0 != ec->proc (ec->cls, "test", EXTRACTOR_METATYPE_COMMENT,
127 EXTRACTOR_METAFORMAT_UTF8, "<no mime>", "Hello world!", 126 EXTRACTOR_METAFORMAT_UTF8, "<no mime>", "Hello world!",
128 strlen ("Hello world!") + 1)) 127 strlen ("Hello world!") + 1))
129 { 128 {
130 fprintf (stderr, "Unexpected return value from 'proc'\n"); 129 fprintf (stderr, "Unexpected return value from 'proc'\n");
131 ABORT (); 130 ABORT ();
132 } 131 }
133 /* The test assumes that client orders us to stop extraction 132 /* The test assumes that client orders us to stop extraction
134 * after seeing "Goodbye!". 133 * after seeing "Goodbye!".
135 */ 134 */
136 if (1 != ec->proc (ec->cls, "test", EXTRACTOR_METATYPE_COMMENT, 135 if (1 != ec->proc (ec->cls, "test", EXTRACTOR_METATYPE_COMMENT,
137 EXTRACTOR_METAFORMAT_UTF8, "<no mime>", "Goodbye!", 136 EXTRACTOR_METAFORMAT_UTF8, "<no mime>", "Goodbye!",
138 strlen ("Goodbye!") + 1)) 137 strlen ("Goodbye!") + 1))
139 { 138 {
140 fprintf (stderr, "Unexpected return value from 'proc'\n"); 139 fprintf (stderr, "Unexpected return value from 'proc'\n");
141 ABORT (); 140 ABORT ();
142 } 141 }
143} 142}
144 143
144
145/* end of test_extractor.c */ 145/* end of test_extractor.c */
diff --git a/src/main/test_file.c b/src/main/test_file.c
index 52803c9..a2d6a5e 100644
--- a/src/main/test_file.c
+++ b/src/main/test_file.c
@@ -46,74 +46,74 @@ static int ret = 2;
46 * @param data hello world or good bye 46 * @param data hello world or good bye
47 * @param data_len number of bytes in data 47 * @param data_len number of bytes in data
48 * @return 0 on hello world, 1 on goodbye 48 * @return 0 on hello world, 1 on goodbye
49 */ 49 */
50static int 50static int
51process_replies (void *cls, 51process_replies (void *cls,
52 const char *plugin_name, 52 const char *plugin_name,
53 enum EXTRACTOR_MetaType type, 53 enum EXTRACTOR_MetaType type,
54 enum EXTRACTOR_MetaFormat format, 54 enum EXTRACTOR_MetaFormat format,
55 const char *data_mime_type, 55 const char *data_mime_type,
56 const char *data, 56 const char *data,
57 size_t data_len) 57 size_t data_len)
58{ 58{
59 if (0 != strcmp (cls, 59 if (0 != strcmp (cls,
60 "main-cls")) 60 "main-cls"))
61 { 61 {
62 fprintf (stderr, "closure invalid\n"); 62 fprintf (stderr, "closure invalid\n");
63 ret = 3; 63 ret = 3;
64 return 1; 64 return 1;
65 } 65 }
66 if (0 != strcmp (plugin_name, 66 if (0 != strcmp (plugin_name,
67 "test")) 67 "test"))
68 { 68 {
69 fprintf (stderr, "plugin name invalid\n"); 69 fprintf (stderr, "plugin name invalid\n");
70 ret = 4; 70 ret = 4;
71 return 1; 71 return 1;
72 } 72 }
73 if (EXTRACTOR_METATYPE_COMMENT != type) 73 if (EXTRACTOR_METATYPE_COMMENT != type)
74 { 74 {
75 fprintf (stderr, "type invalid\n"); 75 fprintf (stderr, "type invalid\n");
76 ret = 5; 76 ret = 5;
77 return 1; 77 return 1;
78 } 78 }
79 if (EXTRACTOR_METAFORMAT_UTF8 != format) 79 if (EXTRACTOR_METAFORMAT_UTF8 != format)
80 { 80 {
81 fprintf (stderr, "format invalid\n"); 81 fprintf (stderr, "format invalid\n");
82 ret = 6; 82 ret = 6;
83 return 1; 83 return 1;
84 } 84 }
85 if ( (NULL == data_mime_type) || 85 if ( (NULL == data_mime_type) ||
86 (0 != strcmp ("<no mime>", 86 (0 != strcmp ("<no mime>",
87 data_mime_type) ) ) 87 data_mime_type) ) )
88 { 88 {
89 fprintf (stderr, "bad mime type\n"); 89 fprintf (stderr, "bad mime type\n");
90 ret = 7; 90 ret = 7;
91 return 1; 91 return 1;
92 } 92 }
93 if ( (2 == ret) && 93 if ( (2 == ret) &&
94 (data_len == strlen (HLO) + 1) && 94 (data_len == strlen (HLO) + 1) &&
95 (0 == strncmp (data, 95 (0 == strncmp (data,
96 HLO, 96 HLO,
97 strlen (HLO))) ) 97 strlen (HLO))) )
98 { 98 {
99#if 0 99#if 0
100 fprintf (stderr, "Received '%s'\n", HLO); 100 fprintf (stderr, "Received '%s'\n", HLO);
101#endif 101#endif
102 ret = 1; 102 ret = 1;
103 return 0; 103 return 0;
104 } 104 }
105 if ( (1 == ret) && 105 if ( (1 == ret) &&
106 (data_len == strlen (GOB) + 1) && 106 (data_len == strlen (GOB) + 1) &&
107 (0 == strncmp (data, 107 (0 == strncmp (data,
108 GOB, 108 GOB,
109 strlen (GOB))) ) 109 strlen (GOB))) )
110 { 110 {
111#if 0 111#if 0
112 fprintf (stderr, "Received '%s'\n", GOB); 112 fprintf (stderr, "Received '%s'\n", GOB);
113#endif 113#endif
114 ret = 0; 114 ret = 0;
115 return 1; 115 return 1;
116 } 116 }
117 fprintf (stderr, "Invalid meta data\n"); 117 fprintf (stderr, "Invalid meta data\n");
118 ret = 8; 118 ret = 8;
119 return 1; 119 return 1;
@@ -132,23 +132,25 @@ main (int argc, char *argv[])
132{ 132{
133 struct EXTRACTOR_PluginList *pl; 133 struct EXTRACTOR_PluginList *pl;
134 134
135 /* change environment to find 'extractor_test' plugin which is 135 /* change environment to find 'extractor_test' plugin which is
136 not installed but should be in the current directory (or .libs) 136 not installed but should be in the current directory (or .libs)
137 on 'make check' */ 137 on 'make check' */
138 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 138 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
139 fprintf (stderr, 139 fprintf (stderr,
140 "Failed to update my environment, plugin loading may fail: %s\n", 140 "Failed to update my environment, plugin loading may fail: %s\n",
141 strerror (errno)); 141 strerror (errno));
142 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)", 142 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)",
143 EXTRACTOR_OPTION_DEFAULT_POLICY); 143 EXTRACTOR_OPTION_DEFAULT_POLICY);
144 if (NULL == pl) 144 if (NULL == pl)
145 { 145 {
146 fprintf (stderr, "failed to load test plugin\n"); 146 fprintf (stderr, "failed to load test plugin\n");
147 return 1; 147 return 1;
148 } 148 }
149 EXTRACTOR_extract (pl, "test_file.dat", NULL, 0, &process_replies, "main-cls"); 149 EXTRACTOR_extract (pl, "test_file.dat", NULL, 0, &process_replies,
150 "main-cls");
150 EXTRACTOR_plugin_remove_all (pl); 151 EXTRACTOR_plugin_remove_all (pl);
151 return ret; 152 return ret;
152} 153}
153 154
155
154/* end of test_file.c */ 156/* end of test_file.c */
diff --git a/src/main/test_gzip.c b/src/main/test_gzip.c
index 87a61cb..071c74c 100644
--- a/src/main/test_gzip.c
+++ b/src/main/test_gzip.c
@@ -46,78 +46,78 @@ static int ret = 2;
46 * @param data hello world or good bye 46 * @param data hello world or good bye
47 * @param data_len number of bytes in data 47 * @param data_len number of bytes in data
48 * @return 0 on hello world, 1 on goodbye 48 * @return 0 on hello world, 1 on goodbye
49 */ 49 */
50static int 50static int
51process_replies (void *cls, 51process_replies (void *cls,
52 const char *plugin_name, 52 const char *plugin_name,
53 enum EXTRACTOR_MetaType type, 53 enum EXTRACTOR_MetaType type,
54 enum EXTRACTOR_MetaFormat format, 54 enum EXTRACTOR_MetaFormat format,
55 const char *data_mime_type, 55 const char *data_mime_type,
56 const char *data, 56 const char *data,
57 size_t data_len) 57 size_t data_len)
58{ 58{
59 if (0 != strcmp (cls, 59 if (0 != strcmp (cls,
60 "main-cls")) 60 "main-cls"))
61 { 61 {
62 fprintf (stderr, "closure invalid\n"); 62 fprintf (stderr, "closure invalid\n");
63 ret = 3; 63 ret = 3;
64 return 1; 64 return 1;
65 } 65 }
66 if (0 == strcmp (plugin_name, 66 if (0 == strcmp (plugin_name,
67 "<zlib>")) 67 "<zlib>"))
68 return 0; /* skip this one */ 68 return 0; /* skip this one */
69 if (0 != strcmp (plugin_name, 69 if (0 != strcmp (plugin_name,
70 "test")) 70 "test"))
71 { 71 {
72 fprintf (stderr, "plugin name invalid: `%s'\n", 72 fprintf (stderr, "plugin name invalid: `%s'\n",
73 plugin_name); 73 plugin_name);
74 ret = 4; 74 ret = 4;
75 return 1; 75 return 1;
76 } 76 }
77 if (EXTRACTOR_METATYPE_COMMENT != type) 77 if (EXTRACTOR_METATYPE_COMMENT != type)
78 { 78 {
79 fprintf (stderr, "type invalid\n"); 79 fprintf (stderr, "type invalid\n");
80 ret = 5; 80 ret = 5;
81 return 1; 81 return 1;
82 } 82 }
83 if (EXTRACTOR_METAFORMAT_UTF8 != format) 83 if (EXTRACTOR_METAFORMAT_UTF8 != format)
84 { 84 {
85 fprintf (stderr, "format invalid\n"); 85 fprintf (stderr, "format invalid\n");
86 ret = 6; 86 ret = 6;
87 return 1; 87 return 1;
88 } 88 }
89 if ( (NULL == data_mime_type) || 89 if ( (NULL == data_mime_type) ||
90 (0 != strcmp ("<no mime>", 90 (0 != strcmp ("<no mime>",
91 data_mime_type) ) ) 91 data_mime_type) ) )
92 { 92 {
93 fprintf (stderr, "bad mime type\n"); 93 fprintf (stderr, "bad mime type\n");
94 ret = 7; 94 ret = 7;
95 return 1; 95 return 1;
96 } 96 }
97 if ( (2 == ret) && 97 if ( (2 == ret) &&
98 (data_len == strlen (HLO) + 1) && 98 (data_len == strlen (HLO) + 1) &&
99 (0 == strncmp (data, 99 (0 == strncmp (data,
100 HLO, 100 HLO,
101 strlen (HLO))) ) 101 strlen (HLO))) )
102 { 102 {
103#if 0 103#if 0
104 fprintf (stderr, "Received '%s'\n", HLO); 104 fprintf (stderr, "Received '%s'\n", HLO);
105#endif 105#endif
106 ret = 1; 106 ret = 1;
107 return 0; 107 return 0;
108 } 108 }
109 if ( (1 == ret) && 109 if ( (1 == ret) &&
110 (data_len == strlen (GOB) + 1) && 110 (data_len == strlen (GOB) + 1) &&
111 (0 == strncmp (data, 111 (0 == strncmp (data,
112 GOB, 112 GOB,
113 strlen (GOB))) ) 113 strlen (GOB))) )
114 { 114 {
115#if 0 115#if 0
116 fprintf (stderr, "Received '%s'\n", GOB); 116 fprintf (stderr, "Received '%s'\n", GOB);
117#endif 117#endif
118 ret = 0; 118 ret = 0;
119 return 1; 119 return 1;
120 } 120 }
121 fprintf (stderr, "Invalid meta data\n"); 121 fprintf (stderr, "Invalid meta data\n");
122 ret = 8; 122 ret = 8;
123 return 1; 123 return 1;
@@ -136,23 +136,25 @@ main (int argc, char *argv[])
136{ 136{
137 struct EXTRACTOR_PluginList *pl; 137 struct EXTRACTOR_PluginList *pl;
138 138
139 /* change environment to find 'extractor_test' plugin which is 139 /* change environment to find 'extractor_test' plugin which is
140 not installed but should be in the current directory (or .libs) 140 not installed but should be in the current directory (or .libs)
141 on 'make check' */ 141 on 'make check' */
142 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 142 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
143 fprintf (stderr, 143 fprintf (stderr,
144 "Failed to update my environment, plugin loading may fail: %s\n", 144 "Failed to update my environment, plugin loading may fail: %s\n",
145 strerror (errno)); 145 strerror (errno));
146 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)", 146 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)",
147 EXTRACTOR_OPTION_DEFAULT_POLICY); 147 EXTRACTOR_OPTION_DEFAULT_POLICY);
148 if (NULL == pl) 148 if (NULL == pl)
149 { 149 {
150 fprintf (stderr, "failed to load test plugin\n"); 150 fprintf (stderr, "failed to load test plugin\n");
151 return 1; 151 return 1;
152 } 152 }
153 EXTRACTOR_extract (pl, "test_file.dat.gz", NULL, 0, &process_replies, "main-cls"); 153 EXTRACTOR_extract (pl, "test_file.dat.gz", NULL, 0, &process_replies,
154 "main-cls");
154 EXTRACTOR_plugin_remove_all (pl); 155 EXTRACTOR_plugin_remove_all (pl);
155 return ret; 156 return ret;
156} 157}
157 158
159
158/* end of test_gzip.c */ 160/* end of test_gzip.c */
diff --git a/src/main/test_ipc.c b/src/main/test_ipc.c
index 5e118fd..4da3ef5 100644
--- a/src/main/test_ipc.c
+++ b/src/main/test_ipc.c
@@ -46,77 +46,77 @@ static int ret = 2;
46 * @param data hello world or good bye 46 * @param data hello world or good bye
47 * @param data_len number of bytes in data 47 * @param data_len number of bytes in data
48 * @return 0 on hello world, 1 on goodbye 48 * @return 0 on hello world, 1 on goodbye
49 */ 49 */
50static int 50static int
51process_replies (void *cls, 51process_replies (void *cls,
52 const char *plugin_name, 52 const char *plugin_name,
53 enum EXTRACTOR_MetaType type, 53 enum EXTRACTOR_MetaType type,
54 enum EXTRACTOR_MetaFormat format, 54 enum EXTRACTOR_MetaFormat format,
55 const char *data_mime_type, 55 const char *data_mime_type,
56 const char *data, 56 const char *data,
57 size_t data_len) 57 size_t data_len)
58{ 58{
59 if (0 != strcmp (cls, 59 if (0 != strcmp (cls,
60 "main-cls")) 60 "main-cls"))
61 { 61 {
62 fprintf (stderr, "closure invalid\n"); 62 fprintf (stderr, "closure invalid\n");
63 ret = 3; 63 ret = 3;
64 return 1; 64 return 1;
65 } 65 }
66 if (0 == strcmp (plugin_name, 66 if (0 == strcmp (plugin_name,
67 "test2")) 67 "test2"))
68 return 0; /* ignore 'test2' plugins */ 68 return 0; /* ignore 'test2' plugins */
69 if (0 != strcmp (plugin_name, 69 if (0 != strcmp (plugin_name,
70 "test")) 70 "test"))
71 { 71 {
72 fprintf (stderr, "plugin name invalid\n"); 72 fprintf (stderr, "plugin name invalid\n");
73 ret = 4; 73 ret = 4;
74 return 1; 74 return 1;
75 } 75 }
76 if (EXTRACTOR_METATYPE_COMMENT != type) 76 if (EXTRACTOR_METATYPE_COMMENT != type)
77 { 77 {
78 fprintf (stderr, "type invalid\n"); 78 fprintf (stderr, "type invalid\n");
79 ret = 5; 79 ret = 5;
80 return 1; 80 return 1;
81 } 81 }
82 if (EXTRACTOR_METAFORMAT_UTF8 != format) 82 if (EXTRACTOR_METAFORMAT_UTF8 != format)
83 { 83 {
84 fprintf (stderr, "format invalid\n"); 84 fprintf (stderr, "format invalid\n");
85 ret = 6; 85 ret = 6;
86 return 1; 86 return 1;
87 } 87 }
88 if ( (NULL == data_mime_type) || 88 if ( (NULL == data_mime_type) ||
89 (0 != strcmp ("<no mime>", 89 (0 != strcmp ("<no mime>",
90 data_mime_type) ) ) 90 data_mime_type) ) )
91 { 91 {
92 fprintf (stderr, "bad mime type\n"); 92 fprintf (stderr, "bad mime type\n");
93 ret = 7; 93 ret = 7;
94 return 1; 94 return 1;
95 } 95 }
96 if ( (2 == ret) && 96 if ( (2 == ret) &&
97 (data_len == strlen (HLO) + 1) && 97 (data_len == strlen (HLO) + 1) &&
98 (0 == strncmp (data, 98 (0 == strncmp (data,
99 HLO, 99 HLO,
100 strlen (HLO))) ) 100 strlen (HLO))) )
101 { 101 {
102#if 0 102#if 0
103 fprintf (stderr, "Received '%s'\n", HLO); 103 fprintf (stderr, "Received '%s'\n", HLO);
104#endif 104#endif
105 ret = 1; 105 ret = 1;
106 return 0; 106 return 0;
107 } 107 }
108 if ( (1 == ret) && 108 if ( (1 == ret) &&
109 (data_len == strlen (GOB) + 1) && 109 (data_len == strlen (GOB) + 1) &&
110 (0 == strncmp (data, 110 (0 == strncmp (data,
111 GOB, 111 GOB,
112 strlen (GOB))) ) 112 strlen (GOB))) )
113 { 113 {
114#if 0 114#if 0
115 fprintf (stderr, "Received '%s'\n", GOB); 115 fprintf (stderr, "Received '%s'\n", GOB);
116#endif 116#endif
117 ret = 0; 117 ret = 0;
118 return 1; 118 return 1;
119 } 119 }
120 fprintf (stderr, "Invalid meta data\n"); 120 fprintf (stderr, "Invalid meta data\n");
121 ret = 8; 121 ret = 8;
122 return 1; 122 return 1;
@@ -138,35 +138,37 @@ main (int argc, char *argv[])
138 size_t i; 138 size_t i;
139 139
140 /* initialize test buffer as expected by test plugin */ 140 /* initialize test buffer as expected by test plugin */
141 for (i=0;i<sizeof(buf);i++) 141 for (i = 0; i<sizeof(buf); i++)
142 buf[i] = (unsigned char) (i % 256); 142 buf[i] = (unsigned char) (i % 256);
143 memcpy (buf, "test", 4); 143 memcpy (buf, "test", 4);
144 144
145 /* change environment to find 'extractor_test' plugin which is 145 /* change environment to find 'extractor_test' plugin which is
146 not installed but should be in the current directory (or .libs) 146 not installed but should be in the current directory (or .libs)
147 on 'make check' */ 147 on 'make check' */
148 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 148 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
149 fprintf (stderr, 149 fprintf (stderr,
150 "Failed to update my environment, plugin loading may fail: %s\n", 150 "Failed to update my environment, plugin loading may fail: %s\n",
151 strerror (errno)); 151 strerror (errno));
152 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)", 152 pl = EXTRACTOR_plugin_add_config (NULL, "test(test)",
153 EXTRACTOR_OPTION_DEFAULT_POLICY); 153 EXTRACTOR_OPTION_DEFAULT_POLICY);
154 pl = EXTRACTOR_plugin_add_config (pl, "test2(test2)", 154 pl = EXTRACTOR_plugin_add_config (pl, "test2(test2)",
155 EXTRACTOR_OPTION_DEFAULT_POLICY); 155 EXTRACTOR_OPTION_DEFAULT_POLICY);
156 if (NULL == pl) 156 if (NULL == pl)
157 { 157 {
158 fprintf (stderr, "failed to load test plugin\n"); 158 fprintf (stderr, "failed to load test plugin\n");
159 return 1; 159 return 1;
160 } 160 }
161 EXTRACTOR_extract (pl, NULL, buf, sizeof (buf), &process_replies, "main-cls"); 161 EXTRACTOR_extract (pl, NULL, buf, sizeof (buf), &process_replies, "main-cls");
162 if (0 == ret) 162 if (0 == ret)
163 { 163 {
164 /* do it again... */ 164 /* do it again... */
165 ret = 2; 165 ret = 2;
166 EXTRACTOR_extract (pl, NULL, buf, sizeof (buf), &process_replies, "main-cls"); 166 EXTRACTOR_extract (pl, NULL, buf, sizeof (buf), &process_replies,
167 } 167 "main-cls");
168 }
168 EXTRACTOR_plugin_remove_all (pl); 169 EXTRACTOR_plugin_remove_all (pl);
169 return ret; 170 return ret;
170} 171}
171 172
173
172/* end of test_ipc.c */ 174/* end of test_ipc.c */
diff --git a/src/main/test_plugin_load_multi.c b/src/main/test_plugin_load_multi.c
index b7958f2..6b30390 100644
--- a/src/main/test_plugin_load_multi.c
+++ b/src/main/test_plugin_load_multi.c
@@ -37,15 +37,15 @@ testLoadPlugins ()
37 el1 = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); 37 el1 = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
38 el2 = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); 38 el2 = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
39 if ((NULL == el1) || (NULL == el2)) 39 if ((NULL == el1) || (NULL == el2))
40 { 40 {
41 fprintf (stderr, 41 fprintf (stderr,
42 "Failed to load default plugins!\n"); 42 "Failed to load default plugins!\n");
43 if (NULL != el1) 43 if (NULL != el1)
44 EXTRACTOR_plugin_remove_all (el1); 44 EXTRACTOR_plugin_remove_all (el1);
45 if (NULL != el2) 45 if (NULL != el2)
46 EXTRACTOR_plugin_remove_all (el2); 46 EXTRACTOR_plugin_remove_all (el2);
47 return 1; 47 return 1;
48 } 48 }
49 EXTRACTOR_plugin_remove_all (el1); 49 EXTRACTOR_plugin_remove_all (el1);
50 EXTRACTOR_plugin_remove_all (el2); 50 EXTRACTOR_plugin_remove_all (el2);
51 return 0; 51 return 0;
@@ -57,16 +57,17 @@ main (int argc, char *argv[])
57{ 57{
58 int ret = 0; 58 int ret = 0;
59 59
60 /* change environment to find 'extractor_test' plugin which is 60 /* change environment to find 'extractor_test' plugin which is
61 not installed but should be in the current directory (or .libs) 61 not installed but should be in the current directory (or .libs)
62 on 'make check' */ 62 on 'make check' */
63 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 63 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
64 fprintf (stderr, 64 fprintf (stderr,
65 "Failed to update my environment, plugin loading may fail: %s\n", 65 "Failed to update my environment, plugin loading may fail: %s\n",
66 strerror (errno)); 66 strerror (errno));
67 ret += testLoadPlugins (); 67 ret += testLoadPlugins ();
68 ret += testLoadPlugins (); 68 ret += testLoadPlugins ();
69 return ret; 69 return ret;
70} 70}
71 71
72
72/* end of test_plugin_load_multi.c */ 73/* end of test_plugin_load_multi.c */
diff --git a/src/main/test_plugin_loading.c b/src/main/test_plugin_loading.c
index ddcfb92..537b703 100644
--- a/src/main/test_plugin_loading.c
+++ b/src/main/test_plugin_loading.c
@@ -30,29 +30,32 @@ main (int argc, char *argv[])
30{ 30{
31 struct EXTRACTOR_PluginList *arg; 31 struct EXTRACTOR_PluginList *arg;
32 32
33 /* change environment to find 'extractor_test' plugin which is 33 /* change environment to find 'extractor_test' plugin which is
34 not installed but should be in the current directory (or .libs) 34 not installed but should be in the current directory (or .libs)
35 on 'make check' */ 35 on 'make check' */
36 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 36 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
37 fprintf (stderr, 37 fprintf (stderr,
38 "Failed to update my environment, plugin loading may fail: %s\n", 38 "Failed to update my environment, plugin loading may fail: %s\n",
39 strerror (errno)); 39 strerror (errno));
40 40
41 /* do some load/unload tests */ 41 /* do some load/unload tests */
42 arg = EXTRACTOR_plugin_add (NULL, "test", NULL, EXTRACTOR_OPTION_DEFAULT_POLICY); 42 arg = EXTRACTOR_plugin_add (NULL, "test", NULL,
43 if (arg != EXTRACTOR_plugin_add (arg, "test", NULL, EXTRACTOR_OPTION_DEFAULT_POLICY)) 43 EXTRACTOR_OPTION_DEFAULT_POLICY);
44 { 44 if (arg != EXTRACTOR_plugin_add (arg, "test", NULL,
45 fprintf (stderr, 45 EXTRACTOR_OPTION_DEFAULT_POLICY))
46 "Could load plugin twice, that should not be allowed\n"); 46 {
47 } 47 fprintf (stderr,
48 "Could load plugin twice, that should not be allowed\n");
49 }
48 arg = EXTRACTOR_plugin_remove (arg, "test"); 50 arg = EXTRACTOR_plugin_remove (arg, "test");
49 if (NULL != arg) 51 if (NULL != arg)
50 { 52 {
51 fprintf (stderr, 53 fprintf (stderr,
52 "add-remove test failed!\n"); 54 "add-remove test failed!\n");
53 return -1; 55 return -1;
54 } 56 }
55 return 0; 57 return 0;
56} 58}
57 59
60
58/* end of test_plugin_loading.c */ 61/* end of test_plugin_loading.c */
diff --git a/src/main/test_trivial.c b/src/main/test_trivial.c
index fac9a91..b0860b4 100644
--- a/src/main/test_trivial.c
+++ b/src/main/test_trivial.c
@@ -30,34 +30,36 @@ static int
30testLoadPlugins (enum EXTRACTOR_Options policy) 30testLoadPlugins (enum EXTRACTOR_Options policy)
31{ 31{
32 struct EXTRACTOR_PluginList *pl; 32 struct EXTRACTOR_PluginList *pl;
33 33
34 if (NULL == (pl = EXTRACTOR_plugin_add_defaults (policy))) 34 if (NULL == (pl = EXTRACTOR_plugin_add_defaults (policy)))
35 { 35 {
36 fprintf (stderr, 36 fprintf (stderr,
37 "Failed to load default plugins!\n"); 37 "Failed to load default plugins!\n");
38 return 1; 38 return 1;
39 } 39 }
40 EXTRACTOR_plugin_remove_all (pl); 40 EXTRACTOR_plugin_remove_all (pl);
41 return 0; 41 return 0;
42} 42}
43 43
44
44int 45int
45main (int argc, char *argv[]) 46main (int argc, char *argv[])
46{ 47{
47 int ret = 0; 48 int ret = 0;
48 49
49 50
50 /* change environment to find 'extractor_test' plugin which is 51 /* change environment to find 'extractor_test' plugin which is
51 not installed but should be in the current directory (or .libs) 52 not installed but should be in the current directory (or .libs)
52 on 'make check' */ 53 on 'make check' */
53 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/")) 54 if (0 != putenv ("LIBEXTRACTOR_PREFIX=." PATH_SEPARATOR_STR ".libs/"))
54 fprintf (stderr, 55 fprintf (stderr,
55 "Failed to update my environment, plugin loading may fail: %s\n", 56 "Failed to update my environment, plugin loading may fail: %s\n",
56 strerror (errno)); 57 strerror (errno));
57 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY); 58 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY);
58 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY); 59 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY);
59 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY); 60 ret += testLoadPlugins (EXTRACTOR_OPTION_DEFAULT_POLICY);
60 return ret; 61 return ret;
61} 62}
62 63
64
63/* end of test_trivial.c */ 65/* end of test_trivial.c */