diff options
Diffstat (limited to 'src/main/extractor_ipc_gnu.c')
-rw-r--r-- | src/main/extractor_ipc_gnu.c | 389 |
1 files changed, 195 insertions, 194 deletions
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 | */ |
194 | unsigned int | 194 | unsigned int |
195 | EXTRACTOR_IPC_shared_memory_change_rc_ (struct EXTRACTOR_SharedMemory *shm, | 195 | EXTRACTOR_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 | */ |
229 | ssize_t | 229 | ssize_t |
230 | EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm, | 230 | EXTRACTOR_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 | */ |
278 | struct EXTRACTOR_Channel * | 278 | struct EXTRACTOR_Channel * |
279 | EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin, | 279 | EXTRACTOR_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 | */ |
426 | ssize_t | 426 | ssize_t |
427 | EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel, | 427 | EXTRACTOR_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 | */ |
465 | int | 465 | int |
466 | EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels, | 466 | EXTRACTOR_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 */ |