From 1a307cb790e0f4e14ce1fbc5ec5105533b3bd820 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Fri, 27 Mar 2009 16:40:07 +0100 Subject: [PATCH] Introduced IsoExternalFilterCommand.behavior and implemented optional shortcut with files of size 0. --- libisofs/filters/external.c | 79 ++++++++++++++++++++++++++++++++----- libisofs/libisofs.h | 5 +++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/libisofs/filters/external.c b/libisofs/filters/external.c index f76aaa3..92fd3a8 100644 --- a/libisofs/filters/external.c +++ b/libisofs/filters/external.c @@ -46,9 +46,33 @@ typedef struct int out_eof; uint8_t pipebuf[2048]; /* buffers in case of EAGAIN on write() */ int pipebuf_fill; + int is_0_run; } ExternalFilterRuntime; +static +int extf_running_new(ExternalFilterRuntime **running, int send_fd, int recv_fd, + pid_t child_pid, int flag) +{ + ExternalFilterRuntime *o; + *running = o = calloc(sizeof(ExternalFilterRuntime), 1); + if (o == NULL) { + return ISO_OUT_OF_MEM; + } + o->send_fd = send_fd; + o->recv_fd = recv_fd; + o->pid = child_pid; + o->in_counter = 0; + o->in_eof = 0; + o->out_counter = 0; + o->out_eof = 0; + memset(o->pipebuf, 0, sizeof(o->pipebuf)); + o->pipebuf_fill = 0; + o->is_0_run = 0; + return 1; +} + + /* * The data payload of an individual IsoStream from External Filter */ @@ -100,6 +124,18 @@ int extf_stream_open_flag(IsoStream *stream, int flag) if (data->running != NULL) { return ISO_FILE_ALREADY_OPENED; } + if (data->cmd->behavior & 1) { + if (iso_stream_get_size(data->orig) == 0) { + /* Do not fork. Place message for .read and .close */; + ret = extf_running_new(&running, -1, -1, 0, 0); + if (ret < 0) { + return ret; + } + running->is_0_run = 1; + data->running = running; + return 1; + } + } if (data->size < 0 && !(flag & 1)) { /* Do the size determination run now, so that the size gets cached and .get_size() will not fail on an opened stream. @@ -132,6 +168,13 @@ int extf_stream_open_flag(IsoStream *stream, int flag) if (child_pid != 0) { /* parent */ +#ifndef NIX + ret = extf_running_new(&running, send_pipe[1], recv_pipe[0], child_pid, + 0); + if (ret < 0) { + goto parent_failed; + } +#else running = calloc(sizeof(ExternalFilterRuntime), 1); if (running == NULL) { ret = ISO_OUT_OF_MEM; @@ -146,6 +189,9 @@ int extf_stream_open_flag(IsoStream *stream, int flag) running->out_eof = 0; memset(running->pipebuf, 0, sizeof(running->pipebuf)); running->pipebuf_fill = 0; + running->is_0_run = 0; +#endif /* NIX */ + data->running = running; /* Give up the child-side pipe ends */ @@ -221,28 +267,34 @@ int extf_stream_open(IsoStream *stream) static int extf_stream_close(IsoStream *stream) { - int ret, status; + int ret, status, is_0_run; ExternalFilterStreamData *data; + if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; - if (data->running != NULL) { + if (data->running == NULL) { + return 1; + } + is_0_run = data->running->is_0_run; + if (!is_0_run) { if(data->running->recv_fd != -1) close(data->running->recv_fd); if(data->running->send_fd != -1) close(data->running->send_fd); ret = waitpid(data->running->pid, &status, WNOHANG); - if (ret == -1) { + if (ret == -1 && data->running->pid != 0) { kill(data->running->pid, SIGKILL); waitpid(data->running->pid, &status, 0); } - - free(data->running); - data->running = NULL; } + free(data->running); + data->running = NULL; + if (is_0_run) + return 1; return iso_stream_close(data->orig); } @@ -263,7 +315,7 @@ int extf_stream_read(IsoStream *stream, void *buf, size_t desired) if (running == NULL) { return ISO_FILE_NOT_OPENED; } - if (running->out_eof) { + if (running->out_eof || running->is_0_run) { return 0; } @@ -428,8 +480,16 @@ void extf_stream_free(IsoStream *stream) } +static +int extf_update_size(IsoStream *stream) +{ + /* By principle size is determined only once */ + return 1; +} + + IsoStreamIface extf_stream_class = { - 0, + 1, "extf", extf_stream_open, extf_stream_close, @@ -437,7 +497,8 @@ IsoStreamIface extf_stream_class = { extf_stream_read, extf_stream_is_repeatable, extf_stream_get_id, - extf_stream_free + extf_stream_free, + extf_update_size }; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 72e4747..e4ce45d 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -4671,6 +4671,11 @@ struct iso_external_filter_command */ char **argv; + /* A bit field which controls behavior variations: + * bit0= Shortcut: 0 sized input will surely yield 0 sized output + * bit1= Do not install filter if the output becomes larger than the input + */ + int behavior; }; typedef struct iso_external_filter_command IsoExternalFilterCommand;