aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-07-24 15:30:16 +0000
committerChristian Grothoff <christian@grothoff.org>2012-07-24 15:30:16 +0000
commite7292e8db0955dc14a3b3e67ae709a186ea68136 (patch)
tree9ef38a6adb4cb9ce01a78427d7fe6a93a28e0e39
parent929bfb08deeab0db8345f144d03e388891695995 (diff)
downloadlibextractor-e7292e8db0955dc14a3b3e67ae709a186ea68136.tar.gz
libextractor-e7292e8db0955dc14a3b3e67ae709a186ea68136.zip
-hxing
-rw-r--r--src/include/extractor.h8
-rw-r--r--src/main/extractor_plugin_main.c414
2 files changed, 215 insertions, 207 deletions
diff --git a/src/include/extractor.h b/src/include/extractor.h
index e862813..a227ea5 100644
--- a/src/include/extractor.h
+++ b/src/include/extractor.h
@@ -418,12 +418,12 @@ struct EXTRACTOR_ExtractContext
418 * @param cls the 'cls' member of this struct 418 * @param cls the 'cls' member of this struct
419 * @param pos position to seek (see 'man lseek') 419 * @param pos position to seek (see 'man lseek')
420 * @param whence how to see (absolute to start, relative, absolute to end) 420 * @param whence how to see (absolute to start, relative, absolute to end)
421 * @return new absolute position, UINT64_MAX on error (i.e. desired position 421 * @return new absolute position, -1 on error (i.e. desired position
422 * does not exist) 422 * does not exist)
423 */ 423 */
424 uint64_t (*seek) (void *cls, 424 int64_t (*seek) (void *cls,
425 int64_t pos, 425 int64_t pos,
426 int whence); 426 int whence);
427 427
428 428
429 /** 429 /**
diff --git a/src/main/extractor_plugin_main.c b/src/main/extractor_plugin_main.c
index 9cf7624..0f5b79f 100644
--- a/src/main/extractor_plugin_main.c
+++ b/src/main/extractor_plugin_main.c
@@ -27,6 +27,7 @@
27#include "plibc.h" 27#include "plibc.h"
28#include "extractor.h" 28#include "extractor.h"
29#include "extractor_datasource.h" 29#include "extractor_datasource.h"
30#include "extractor_plugins.h"
30#include "extractor_ipc.h" 31#include "extractor_ipc.h"
31#include "extractor_plugin_main.h" 32#include "extractor_plugin_main.h"
32#include <dirent.h> 33#include <dirent.h>
@@ -36,26 +37,62 @@
36#include <signal.h> 37#include <signal.h>
37 38
38 39
39
40/** 40/**
41 * Opens a file (for later mmapping). 41 * Closure we use for processing requests inside the helper process.
42 * This is POSIX variant of the plugin_open_* function. 42 */
43 * Closes a file is already opened, closes it before opening a new one. 43struct ProcessingContext
44 * Destroy shared memory area.
45 *
46 * @param plugin plugin context
47 * @param shm_name name of the file to open.
48 * @return file id (-1 on error). That is, the result of open() syscall.
49 */
50static int
51plugin_open_file (struct EXTRACTOR_PluginList *plugin,
52 const char *shm_name)
53{ 44{
54 if (plugin->shm_id != -1) 45 /**
55 close (plugin->shm_id); 46 * Our plugin handle.
56 plugin->shm_id = open (shm_name, O_RDONLY, 0); 47 */
57 return plugin->shm_id; 48 struct EXTRACTOR_PluginList *plugin;
58} 49
50 /**
51 * Shared memory area.
52 */
53 void *shm;
54
55 /**
56 * Overall size of the file.
57 */
58 uint64_t file_size;
59
60 /**
61 * Current read offset when reading from the SHM.
62 */
63 uint64_t read_position;
64
65 /**
66 * Current offset of the SHM in the file.
67 */
68 uint64_t shm_off;
69
70 /**
71 * Handle to the shared memory.
72 */
73 int shm_id;
74
75 /**
76 * Size of the shared memory map.
77 */
78 uint32_t shm_map_size;
79
80 /**
81 * Number of bytes ready in SHM.
82 */
83 uint32_t shm_ready_bytes;
84
85 /**
86 * Input stream.
87 */
88 int in;
89
90 /**
91 * Output stream.
92 */
93 int out;
94};
95
59 96
60 97
61/** 98/**
@@ -69,8 +106,12 @@ plugin_open_file (struct EXTRACTOR_PluginList *plugin,
69 * @return new absolute position, -1 on error 106 * @return new absolute position, -1 on error
70 */ 107 */
71static int64_t 108static int64_t
72pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence) 109plugin_env_seek (void *cls,
110 int64_t pos,
111 int whence)
73{ 112{
113 struct ProcessingContext *pc = cls;
114
74 switch (whence) 115 switch (whence)
75 { 116 {
76 case SEEK_CUR: 117 case SEEK_CUR:
@@ -123,13 +164,6 @@ pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence)
123} 164}
124 165
125 166
126static int64_t
127pl_get_fsize (struct EXTRACTOR_PluginList *plugin)
128{
129 return plugin->fsize;
130}
131
132
133/** 167/**
134 * Fills @data with a pointer to the data buffer. 168 * Fills @data with a pointer to the data buffer.
135 * Equivalent to read(), except you don't have to allocate and free 169 * Equivalent to read(), except you don't have to allocate and free
@@ -141,9 +175,12 @@ pl_get_fsize (struct EXTRACTOR_PluginList *plugin)
141 * @param count number of bytes to read 175 * @param count number of bytes to read
142 * @return number of bytes (<= count) avalable in @data, -1 on error 176 * @return number of bytes (<= count) avalable in @data, -1 on error
143 */ 177 */
144static int64_t 178static ssize_t
145pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t count) 179plugin_env_read (void *cls,
180 unsigned char **data, size_t count)
146{ 181{
182 struct ProcessingContext *pc = cls;
183
147 *data = NULL; 184 *data = NULL;
148 if (count > MAX_READ) 185 if (count > MAX_READ)
149 return -1; 186 return -1;
@@ -166,41 +203,11 @@ pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t count
166} 203}
167 204
168 205
169/** 206static uint64_t
170 * Initializes an extracting session for a plugin. 207plugin_env_get_size (void *cls)
171 * opens the file/shm (only in OPMODE_FILE)
172 * sets shm_ptr to NULL (unmaps it, if it was mapped)
173 * sets position to 0
174 * initializes file size to 'fsize' (may be -1)
175 * sets seek request to 0
176 *
177 * @param plugin plugin context
178 * @param operation_mode the mode of operation (OPMODE_*)
179 * @param fsize size of the source file (may be -1)
180 * @param shm_name name of the shm or file to open
181 * @return 0 on success, non-0 on error.
182 */
183static int
184init_state_method (struct EXTRACTOR_PluginList *plugin,
185 uint8_t operation_mode,
186 int64_t fsize,
187 const char *shm_name)
188{ 208{
189 plugin->seek_request = 0; 209 struct ProcessingContext *pc = cls;
190 if (plugin->shm_ptr != NULL) 210 return pc->file_size;
191 munmap (plugin->shm_ptr, plugin->map_size);
192 plugin->shm_ptr = NULL;
193 if (operation_mode == OPMODE_FILE)
194 {
195 if (-1 == plugin_open_file (plugin, shm_name))
196 return 1;
197 }
198 else if (-1 == plugin_open_shm (plugin, shm_name))
199 return 1;
200 plugin->fsize = fsize;
201 plugin->shm_pos = 0;
202 plugin->fpos = 0;
203 return 0;
204} 211}
205 212
206 213
@@ -208,7 +215,7 @@ init_state_method (struct EXTRACTOR_PluginList *plugin,
208 * Function called by a plugin in a child process. Transmits 215 * Function called by a plugin in a child process. Transmits
209 * the meta data back to the parent process. 216 * the meta data back to the parent process.
210 * 217 *
211 * @param cls closure, "int*" of the FD for transmission 218 * @param cls closure, "struct ProcessingContext" with the FD for transmission
212 * @param plugin_name name of the plugin that produced this value; 219 * @param plugin_name name of the plugin that produced this value;
213 * special values can be used (i.e. '<zlib>' for zlib being 220 * special values can be used (i.e. '<zlib>' for zlib being
214 * used in the main libextractor library and yielding 221 * used in the main libextractor library and yielding
@@ -222,16 +229,17 @@ init_state_method (struct EXTRACTOR_PluginList *plugin,
222 * @return 0 to continue extracting, 1 to abort (transmission error) 229 * @return 0 to continue extracting, 1 to abort (transmission error)
223 */ 230 */
224static int 231static int
225transmit_reply (void *cls, 232plugin_env_send_proc (void *cls,
226 const char *plugin_name, 233 const char *plugin_name,
227 enum EXTRACTOR_MetaType type, 234 enum EXTRACTOR_MetaType type,
228 enum EXTRACTOR_MetaFormat format, 235 enum EXTRACTOR_MetaFormat format,
229 const char *data_mime_type, 236 const char *data_mime_type,
230 const char *data, 237 const char *data,
231 size_t data_len) 238 size_t data_len)
232{ 239{
240 struct ProcessingContext *pc = cls;
233 static const unsigned char meta_byte = MESSAGE_META; 241 static const unsigned char meta_byte = MESSAGE_META;
234 int *cpipe_out = cls; 242 int cpipe_out = pc->out;
235 struct IpcHeader hdr; 243 struct IpcHeader hdr;
236 size_t mime_len; 244 size_t mime_len;
237 245
@@ -263,132 +271,126 @@ transmit_reply (void *cls,
263 271
264 272
265/** 273/**
266 * Main loop function for plugins. Reads a message from the plugin 274 * Handle an init message. The opcode itself has already been read.
267 * input pipe and acts on it.
268 * 275 *
269 * @param plugin plugin context 276 * @param pc processing context
270 * @param in input stream with incoming requests 277 * @return 0 on success, -1 on error
271 * @param out output stream for sending responses 278 */
272 */ 279static int
273static void 280handle_init_message (struct ProcessingContext *pc)
274process_requests (struct EXTRACTOR_PluginList *plugin,
275 int in,
276 int out)
277{ 281{
278 int read_result1; 282 struct InitMessage init;
279 int read_result2;
280 int read_result3;
281 int read_result4;
282 unsigned char code;
283 char *shm_name = NULL;
284 size_t shm_name_len;
285 int extract_reply;
286 struct IpcHeader hdr;
287 int do_break;
288#ifdef WINDOWS
289 HANDLE map;
290 MEMORY_BASIC_INFORMATION mi;
291#endif
292 283
293 /* The point of recursing into this function is to request 284 if (NULL != pc->shm)
294 * a seek from LE server and wait for a reply. This snipper 285 return -1;
295 * requests a seek. 286 if (sizeof (struct InitMessage) - 1
296 */ 287 != read (pc->in,
297 if (plugin->waiting_for_update == 1) 288 &init.reserved,
289 sizeof (struct InitMessage) - 1))
290 return -1;
291 if (init.shm_name_length > MAX_SHM_NAME)
292 return -1;
298 { 293 {
299 unsigned char seek_byte = MESSAGE_SEEK; 294 char shm_name[init.shm_name_length + 1];
300 if (write (out, &seek_byte, 1) != 1) 295
296 if (init.shm_name_length
297 != read (pc->in,
298 shm_name,
299 init.shm_name_length))
301 return -1; 300 return -1;
302 if (write (out, &plugin->seek_request, sizeof (int64_t)) != sizeof (int64_t)) 301 shm_name[init.shm_name_length] = '\0';
302
303 pc->shm_map_size = init.shm_map_size;
304#if WINDOWS
305 pc->shm_ptr = MapViewOfFile (pc->shm_id, FILE_MAP_READ, 0, 0, 0);
306 if (NULL == pc->shm_ptr)
307 return -1;
308#else
309 pc->shm_id = open (shm_name, O_RDONLY, 0);
310 if (-1 == pc->shm_id)
303 return -1; 311 return -1;
312 pc->shm = mmap (NULL,
313 pc->shm_map_size,
314 PROT_READ,
315 MAP_SHARED,
316 pc->shm_id, 0);
317 if ( ((void*) -1) == pc->shm)
318 return -1;
319#endif
304 } 320 }
321 return 0;
322}
305 323
306 memset (&hdr, 0, sizeof (hdr)); 324
307 do_break = 0; 325/**
308 while (!do_break) 326 * Handle a start message. The opcode itself has already been read.
309 { 327 *
310 read_result1 = read (in, &code, 1); 328 * @param pc processing context
311 if (read_result1 <= 0) 329 * @return 0 on success, -1 on error
312 break; 330 */
313 switch (code) 331static int
332handle_start_message (struct ProcessingContext *pc)
333{
334 struct StartMessage start;
335 struct EXTRACTOR_ExtractContext ec;
336
337 if (sizeof (struct StartMessage) - 1
338 != read (pc->in,
339 &start.reserved,
340 sizeof (struct StartMessage) - 1))
341 return -1;
342 pc->shm_ready_bytes = start.shm_ready_bytes;
343 pc->file_size = start.shm_file_size;
344 pc->read_position = 0;
345 pc->shm_off = 0;
346 ec.cls = pc;
347 ec.config = pc->plugin->plugin_options;
348 ec.read = &plugin_env_read;
349 ec.seek = &plugin_env_seek;
350 ec.get_size = &plugin_env_get_size;
351 ec.proc = &plugin_env_send_proc;
352 pc->plugin->extract_method (&ec);
353}
354
355
356/**
357 * Main loop function for plugins. Reads a message from the plugin
358 * input pipe and acts on it.
359 *
360 * @param pc processing context
361 */
362static void
363process_requests (struct ProcessingContext *pc)
364{
365 while (1)
314 { 366 {
315 case MESSAGE_INIT_STATE: 367 unsigned char code;
316 read_result2 = read (in, &plugin->operation_mode, sizeof (uint8_t)); 368
317 read_result3 = read (in, &plugin->fsize, sizeof (int64_t)); 369 if (1 != read (pc->in, &code, 1))
318 read_result4 = read (in, &shm_name_len, sizeof (size_t)); 370 break;
319 if ((read_result2 < sizeof (uint8_t)) || 371 switch (code)
320 (read_result3 < sizeof (int64_t)) || 372 {
321 (read_result4 < sizeof (size_t))) 373 case MESSAGE_INIT_STATE:
322 { 374 if (0 != handle_init_message (pc))
323 do_break = 1; 375 return;
324 break; 376 break;
325 } 377 case MSG_EXTRACT_START:
326 if (plugin->operation_mode != OPMODE_MEMORY && 378 if (0 != handle_start_message (pc))
327 plugin->operation_mode != OPMODE_DECOMPRESS && 379 return;
328 plugin->operation_mode != OPMODE_FILE) 380 case MSG_UPDATED_SHM:
329 { 381 /* not allowed here, we're not waiting for SHM to move! */
330 do_break = 1; 382 return;
331 break; 383 case MSG_DISCARD_STATE:
332 } 384 /* odd, we're already in the start state... */
333 if ((plugin->operation_mode == OPMODE_MEMORY || 385 continue;
334 plugin->operation_mode == OPMODE_DECOMPRESS) && 386 default:
335 shm_name_len > MAX_SHM_NAME) 387 /* error, unexpected message */
336 { 388 return;
337 do_break = 1; 389 }
338 break; 390 }
339 } 391}
340 /* Fsize may be -1 only in decompression mode */ 392
341 if (plugin->operation_mode != OPMODE_DECOMPRESS && plugin->fsize <= 0) 393#if 0
342 {
343 do_break = 1;
344 break;
345 }
346 if (shm_name != NULL)
347 free (shm_name);
348 shm_name = malloc (shm_name_len);
349 if (shm_name == NULL)
350 {
351 do_break = 1;
352 break;
353 }
354 read_result2 = read (in, shm_name, shm_name_len);
355 if (read_result2 < shm_name_len)
356 {
357 do_break = 1;
358 break;
359 }
360 shm_name[shm_name_len - 1] = '\0';
361 do_break = init_state_method (plugin, plugin->operation_mode, plugin->fsize, shm_name);
362 /* in OPMODE_MEMORY and OPMODE_FILE we can start extracting right away,
363 * there won't be UPDATED_SHM message, and we don't need it
364 */
365 if (!do_break && (plugin->operation_mode == OPMODE_MEMORY ||
366 plugin->operation_mode == OPMODE_FILE))
367 {
368 extract_reply = plugin->extract_method (plugin, transmit_reply, &out);
369 unsigned char done_byte = MESSAGE_DONE;
370 if (write (out, &done_byte, 1) != 1)
371 {
372 do_break = 1;
373 break;
374 }
375 if ((plugin->specials != NULL) &&
376 (NULL != strstr (plugin->specials, "force-kill")))
377 {
378 /* we're required to die after each file since this
379 plugin only supports a single file at a time */
380#if !WINDOWS
381 fsync (out);
382#else
383 _commit (out);
384#endif
385 _exit (0);
386 }
387 }
388 break;
389 case MESSAGE_DISCARD_STATE:
390 discard_state_method (plugin);
391 break;
392 case MESSAGE_UPDATED_SHM: 394 case MESSAGE_UPDATED_SHM:
393 if (plugin->operation_mode == OPMODE_DECOMPRESS) 395 if (plugin->operation_mode == OPMODE_DECOMPRESS)
394 { 396 {
@@ -413,7 +415,7 @@ process_requests (struct EXTRACTOR_PluginList *plugin,
413 } 415 }
414#else 416#else
415 if ((plugin->map_handle == 0) || 417 if ((plugin->map_handle == 0) ||
416 (NULL == (plugin->shm_ptr = MapViewOfFile (plugin->map_handle, FILE_MAP_READ, 0, 0, 0)))) 418 (NULL == (plugin->shm_ptr =
417 { 419 {
418 do_break = 1; 420 do_break = 1;
419 break; 421 break;
@@ -478,20 +480,8 @@ process_requests (struct EXTRACTOR_PluginList *plugin,
478 } 480 }
479 } 481 }
480 } 482 }
481 else
482 {
483 /* This is mostly to safely skip unrelated messages */
484 int64_t t;
485 size_t t2;
486 read_result2 = read (in, &t, sizeof (int64_t));
487 read_result3 = read (in, &t2, sizeof (size_t));
488 read_result4 = read (in, &t, sizeof (int64_t));
489 }
490 break;
491 }
492 }
493 return 0;
494} 483}
484#endif
495 485
496 486
497#ifndef WINDOWS 487#ifndef WINDOWS
@@ -536,6 +526,8 @@ void
536EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin, 526EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin,
537 int in, int out) 527 int in, int out)
538{ 528{
529 struct ProcessingContext pc;
530
539 if (0 != EXTRACTOR_plugin_load_ (plugin)) 531 if (0 != EXTRACTOR_plugin_load_ (plugin))
540 { 532 {
541#if DEBUG 533#if DEBUG
@@ -560,7 +552,23 @@ EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin,
560 open_dev_null (1, O_WRONLY); 552 open_dev_null (1, O_WRONLY);
561#endif 553#endif
562 } 554 }
563 process_requests (plugin, in, out); 555 pc.plugin = plugin;
556 pc.in = in;
557 pc.out = out;
558 pc.shm_id = -1;
559 pc.shm = NULL;
560 pc.shm_map_size = 0;
561 process_requests (&pc);
562#if WINDOWS
563 if (NULL != pc.shm_ptr)
564 UnmapViewOfFile (pc.shm_ptr);
565#else
566 if ( (NULL != pc.shm_ptr) &&
567 (((void*) 1) != pc.shm_ptr) )
568 munmap (pc.shm_ptr, pc.shm_map_size);
569 if (-1 != pc.shm_id)
570 (void) close (pc.shm_id);
571#endif
564} 572}
565 573
566 574