diff --git a/libisofs/filter.c b/libisofs/filter.c index a7f2be6..27c72e1 100644 --- a/libisofs/filter.c +++ b/libisofs/filter.c @@ -47,3 +47,20 @@ int iso_file_add_filter(IsoFile *file, FilterContext *filter, int flag) file->stream = filtered; return ISO_SUCCESS; } + + +/* ts A90328 */ +int iso_file_remove_filter(IsoFile *file, int flag) +{ + IsoStream *file_stream, *input_stream; + + file_stream = file->stream; + input_stream = iso_stream_get_input_stream(file_stream, 0); + if (input_stream == NULL) + return 0; + file->stream = input_stream; + iso_stream_ref(input_stream); /* Protect against _unref(file_stream) */ + iso_stream_unref(file_stream); + return 1; +} + diff --git a/libisofs/filters/external.c b/libisofs/filters/external.c index c1ce501..4462953 100644 --- a/libisofs/filters/external.c +++ b/libisofs/filters/external.c @@ -473,6 +473,9 @@ void extf_stream_free(IsoStream *stream) return; } data = stream->data; + if (data->running != NULL) { + extf_stream_close(stream); + } iso_stream_unref(data->orig); if (data->cmd->refcount > 0) data->cmd->refcount--; @@ -488,8 +491,20 @@ int extf_update_size(IsoStream *stream) } +IsoStream *extf_get_input_stream(IsoStream *stream, int flag) +{ + ExternalFilterStreamData *data; + + if (stream == NULL) { + return NULL; + } + data = stream->data; + return data->orig; +} + + IsoStreamIface extf_stream_class = { - 1, + 2, "extf", extf_stream_open, extf_stream_close, @@ -498,7 +513,8 @@ IsoStreamIface extf_stream_class = { extf_stream_is_repeatable, extf_stream_get_id, extf_stream_free, - extf_update_size + extf_update_size, + extf_get_input_stream }; diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 4b3f4e2..c0544a1 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -3229,18 +3229,28 @@ int iso_file_get_old_image_sections(IsoFile *file, int *section_count, * to get the sections. This break encapsultation, but safes memory as * we don't need to store the sections in the IsoFile node. */ - IsoStream *stream = file->stream; + IsoStream *stream = file->stream, *input_stream; FSrcStreamData *data; ImageFileSourceData *ifsdata; - /* <<< ts A90327 : provisory patch on SIGSEGV */ + /* ts A90328 : Get the most original stream */ + while (1) { + input_stream = iso_stream_get_input_stream(stream, 0); + if (input_stream == NULL || input_stream == stream) + break; + stream = input_stream; + } + + /* ts A90327 : From here on it must be a stream with FSrcStreamData. */ + /* ??? Shall one rather check : + stream->class == extern IsoStreamIface fsrc_stream_class + (its storage location is global in stream.c) + */ if (stream->class->type[0] != 'f' || stream->class->type[1] != 's' || stream->class->type[2] != 'r' || stream->class->type[3] != 'c') return 0; - /* >>> need a method to get the most original stream */ - - data = file->stream->data; + data = stream->data; ifsdata = data->src->data; *section_count = ifsdata->nsections; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 30fccfe..17c2ec8 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -766,10 +766,13 @@ extern ino_t serial_id; struct IsoStream_Iface { /* - * Current version of the interface, set to 1. - * - * -version 1 (since 0.6.8) + * Current version of the interface, set to 1 or 2. + * Version 0 (since 0.6.4) + * deprecated but still valid. + * Version 1 (since 0.6.8) * update_size() added. + * Version 2 (since 0.6.18) + * get_input_stream() added. A filter stream should have version 2. */ int version; @@ -846,6 +849,7 @@ struct IsoStream_Iface void (*free)(IsoStream *stream); /** + * Present if .version is 1 or higher: * Updates the size of the IsoStream with the current size of the * underlying source. After calling this, get_size() will return * the new size. This should never be called after @@ -856,9 +860,26 @@ struct IsoStream_Iface * * @return * 1 if ok, < 0 on error (has to be a valid libisofs error code) + * * @since 0.6.8 */ int (*update_size)(IsoStream *stream); + + /** + * Present if .version is 2 or higher: + * Obtains the eventual input stream of a filter stream. + * @param stream + * The eventual filter stream to be inquired. + * @param flag + * Bitfield for control purposes. Submit 0 for now. + * @return + * The input stream, if one exists. Elsewise NULL. + * No extra reference to the stream is taken by this call. + * + * @since 0.6.18 + */ + IsoStream *(*get_input_stream)(IsoStream *stream, int flag); + }; /** @@ -4045,6 +4066,22 @@ int iso_stream_update_size(IsoStream *stream); void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id); +/* ts A90328 */ +/** + * Obtain the eventual input stream of a filter stream. + * @param stream + * The eventual filter stream to be inquired. + * @param flag + * Bitfield for control purposes. Submit 0 for now. + * @return + * The input stream, if one exists. Elsewise NULL. + * No extra reference to the stream is taken by this call. + * + * @since 0.6.18 + */ +IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag); + + /************ Error codes and return values for libisofs ********************/ /** successfully execution */ @@ -4685,6 +4722,8 @@ typedef struct iso_external_filter_command IsoExternalFilterCommand; * Install an external filter command on top of the content stream of a data * file. The filter process must be repeatable. It will be run once by this * call in order to cache the output size. + * This call creates a new IsoStream which uses the existing IsoStream of the + * data file as input. * iso_file_get_stream() will return the filter stream. * iso_stream_get_size() will return the cached size of the filtered data, * iso_stream_open() will start again the external filter process, @@ -4705,6 +4744,27 @@ typedef struct iso_external_filter_command IsoExternalFilterCommand; int iso_file_add_external_filter(IsoFile *file, IsoExternalFilterCommand *cmd, int flag); +/* ts A90328 */ +/** + * Delete the top filter stream from a data file. This is the most recent one + * which was added by iso_file_add_*_filter(). + * Caution: One should not do this while the IsoStream of the file is opened. + * For now there is no general way to determine this state. + * Filter stream implementations are urged to eventually call .close() + * inside method .free() . This will close the input stream too. + * @param file + * The data file node which shall get rid of one layer of content + * filtering. + * @param flag + * Bitfield for control purposes, unused yet, submit 0. + * @return + * 1 on success, 0 if no filter was present + * <0 on error + * + * @since 0.6.18 + */ +int iso_file_remove_filter(IsoFile *file, int flag); + /* ------------------------------------------------------------------------- */ diff --git a/libisofs/stream.c b/libisofs/stream.c index 3a996e6..8ecc56b 100644 --- a/libisofs/stream.c +++ b/libisofs/stream.c @@ -642,3 +642,14 @@ void iso_stream_get_file_name(IsoStream *stream, char *name) strcpy(name, "UNKNOWN SOURCE"); } } + +/* ts A90328 API */ +IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag) +{ + IsoStreamIface* class = stream->class; + + if (class->version < 2) + return NULL; + return class->get_input_stream(stream, 0); +} +