From 8c4682ae92bf86abdc812496d25b3a988cddf7ab Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 12 May 2009 09:29:06 +0200 Subject: [PATCH] IsoStream version 3 with cmp_ino(), new API call iso_stream_cmp_ino() for proper comparison of filtered streams --- libisofs/filters/external.c | 27 ++++++++++++- libisofs/filters/gzip.c | 28 ++++++++++++-- libisofs/filters/zisofs.c | 28 ++++++++++++-- libisofs/libisofs.h | 77 +++++++++++++++++++++++++++++++++---- libisofs/stream.c | 17 ++++++-- libisofs/stream.h | 3 -- 6 files changed, 156 insertions(+), 24 deletions(-) diff --git a/libisofs/filters/external.c b/libisofs/filters/external.c index ae72a98..163beeb 100644 --- a/libisofs/filters/external.c +++ b/libisofs/filters/external.c @@ -594,8 +594,13 @@ IsoStream *extf_get_input_stream(IsoStream *stream, int flag) } +static +int extf_cmp_ino(IsoStream *s1, IsoStream *s2); +/* Function is defined after definition of extf_stream_class */ + + IsoStreamIface extf_stream_class = { - 2, + 3, "extf", extf_stream_open, extf_stream_close, @@ -605,10 +610,28 @@ IsoStreamIface extf_stream_class = { extf_stream_get_id, extf_stream_free, extf_update_size, - extf_get_input_stream + extf_get_input_stream, + extf_cmp_ino }; +static +int extf_cmp_ino(IsoStream *s1, IsoStream *s2) +{ + ExternalFilterStreamData *data1, *data2; + + if (s1->class != &extf_stream_class || s2->class != &extf_stream_class) + return iso_stream_cmp_ino(s1, s2, 1); + data1 = (ExternalFilterStreamData*) s1->data; + data2 = (ExternalFilterStreamData*) s2->data; + if (data1->cmd != data2->cmd) + return (data1->cmd < data2->cmd ? -1 : 1); + return iso_stream_cmp_ino(data1->orig, data2->orig, 0); +} + + +/* ------------------------------------------------------------------------- */ + static void extf_filter_free(FilterContext *filter) { diff --git a/libisofs/filters/gzip.c b/libisofs/filters/gzip.c index f88d914..deccf27 100644 --- a/libisofs/filters/gzip.c +++ b/libisofs/filters/gzip.c @@ -521,8 +521,12 @@ IsoStream *gzip_get_input_stream(IsoStream *stream, int flag) } +static +int gzip_cmp_ino(IsoStream *s1, IsoStream *s2); + + IsoStreamIface gzip_stream_compress_class = { - 2, + 3, "gzip", gzip_stream_open, gzip_stream_close, @@ -532,12 +536,13 @@ IsoStreamIface gzip_stream_compress_class = { gzip_stream_get_id, gzip_stream_free, gzip_update_size, - gzip_get_input_stream + gzip_get_input_stream, + gzip_cmp_ino }; IsoStreamIface gzip_stream_uncompress_class = { - 2, + 3, "pizg", gzip_stream_open, gzip_stream_close, @@ -547,9 +552,24 @@ IsoStreamIface gzip_stream_uncompress_class = { gzip_stream_get_id, gzip_stream_free, gzip_update_size, - gzip_get_input_stream + gzip_get_input_stream, + gzip_cmp_ino }; + +static +int gzip_cmp_ino(IsoStream *s1, IsoStream *s2) +{ + if (s1->class != s2->class || (s1->class != &gzip_stream_compress_class && + s2->class != &gzip_stream_compress_class)) + return iso_stream_cmp_ino(s1, s2, 1); + return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), + iso_stream_get_input_stream(s2, 0), 0); +} + + +/* ------------------------------------------------------------------------- */ + static void gzip_filter_free(FilterContext *filter) diff --git a/libisofs/filters/zisofs.c b/libisofs/filters/zisofs.c index c7e3b75..0026a23 100644 --- a/libisofs/filters/zisofs.c +++ b/libisofs/filters/zisofs.c @@ -775,8 +775,12 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag) } +static +int ziso_cmp_ino(IsoStream *s1, IsoStream *s2); + + IsoStreamIface ziso_stream_compress_class = { - 2, + 3, "ziso", ziso_stream_open, ziso_stream_close, @@ -786,12 +790,13 @@ IsoStreamIface ziso_stream_compress_class = { ziso_stream_get_id, ziso_stream_free, ziso_update_size, - ziso_get_input_stream + ziso_get_input_stream, + ziso_cmp_ino }; IsoStreamIface ziso_stream_uncompress_class = { - 2, + 3, "osiz", ziso_stream_open, ziso_stream_close, @@ -801,10 +806,25 @@ IsoStreamIface ziso_stream_uncompress_class = { ziso_stream_get_id, ziso_stream_free, ziso_update_size, - ziso_get_input_stream + ziso_get_input_stream, + ziso_cmp_ino }; +static +int ziso_cmp_ino(IsoStream *s1, IsoStream *s2) +{ + if (s1->class != s2->class || (s1->class != &ziso_stream_compress_class && + s2->class != &ziso_stream_uncompress_class)) + iso_stream_cmp_ino(s1, s2, 1); + return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), + iso_stream_get_input_stream(s2, 0), 0); +} + + +/* ------------------------------------------------------------------------- */ + + static void ziso_filter_free(FilterContext *filter) { diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index c32f42b..8d187ea 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -759,8 +759,11 @@ typedef struct IsoStream_Iface IsoStreamIface; extern ino_t serial_id; /** - * Interface definition for IsoStream methods. - * + * Interface definition for IsoStream methods. It is public to allow + * implementation of own stream types. + * The methods defined here typically make use of stream.data which points + * to the individual state data of stream instances. + * * @since 0.6.4 */ struct IsoStream_Iface @@ -773,6 +776,8 @@ struct IsoStream_Iface * update_size() added. * Version 2 (since 0.6.18) * get_input_stream() added. A filter stream must have version 2. + * Version 3 (since 0.6.20) + * compare() added. A filter stream should have version 3. */ int version; @@ -856,7 +861,6 @@ 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 @@ -869,24 +873,61 @@ struct IsoStream_Iface * 1 if ok, < 0 on error (has to be a valid libisofs error code) * * @since 0.6.8 + * Present if .version is 1 or higher. */ 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. + * The eventual filter stream to be inquired. * @param flag - * Bitfield for control purposes. Submit 0 for now. + * 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. + * The input stream, if one exists. Elsewise NULL. + * No extra reference to the stream is taken by this call. * * @since 0.6.18 + * Present if .version is 2 or higher. */ IsoStream *(*get_input_stream)(IsoStream *stream, int flag); + /* ts A90511 */ + /** + * Compare two streams whether they are based on the same input and will + * produce the same output. If in any doubt, then this comparison should + * indicate no match. A match might allow hardlinking of IsoFile objects. + * This function has to establish an equivalence and order relation: + * A = A, if A = B then B = A, if A = B and B = C then A = C, + * if A < B then not B < A, if A < B and B < C then A < C + * + * A function s1.(*cmp_ino)() must only accept stream s2 if function + * s2.(*cmp_ino)() would accept s1. Best is to accept only the own stream + * type or to have the same function for a family of similar stream types. + * + * If the function cannot accept one of the given stream types, then + * the decision must be delegated to + * iso_stream_cmp_ino(s1, s2, 1); + * This is also appropriate if one has reason to implement stream.cmp_ino() + * without special comparison algorithm. + * With filter streams the decision whether the underlying chains of + * streams match should be delegated to + * iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), + * iso_stream_get_input_stream(s2, 0), 0); + * + * @param s1 + * The first stream to compare. Expect foreign stream types. + * @param s2 + * The second stream to compare. Expect foreign stream types. + * @return + * -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2 + * + * @since 0.6.20 + * Present if .version is 3 or higher. + */ + int (*cmp_ino)(IsoStream *s1, IsoStream *s2); + }; /** @@ -4162,6 +4203,26 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, */ char *iso_stream_get_source_path(IsoStream *stream, int flag); +/* ts A90502 */ +/** + * Compare two streams whether they are based on the same input and will + * produce the same output. If in any doubt, then this comparison will + * indicate no match. + * + * @param s1 + * The first stream to compare. + * @param s2 + * The second stream to compare. + * @return + * -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2 + * @param flag + * bit0= do not use s1->class->compare() even if available + * (e.g. because iso_stream_cmp_ino(0 is called as fallback + * from said stream->class->compare()) + * + * @since 0.6.20 + */ +int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag); /* --------------------------------- AAIP --------------------------------- */ diff --git a/libisofs/stream.c b/libisofs/stream.c index 09af2de..30e52a3 100644 --- a/libisofs/stream.c +++ b/libisofs/stream.c @@ -728,10 +728,11 @@ int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag) return 0; } -/* ts A90502 */ -/* The former core of iso_file_src_cmp() */ +/* ts A90511 */ +/* API */ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag) { + int ret; unsigned int fs_id1, fs_id2; dev_t dev_id1, dev_id2; ino_t ino_id1, ino_id2; @@ -741,9 +742,19 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag) static int report_counter = 0; static int debug = 1; - if (s1 == s2) { + if (s1 == s2) return 0; + if (s1 == NULL) + return -1; + if (s2 == NULL) + return 1; + + if (s1->class->version >= 3 && !(flag & 1)) { + /* Filters may have smarter methods to compare themselves with others */ + ret = s1->class->cmp_ino(s1, s2); + return ret; } + iso_stream_get_id(s1, &fs_id1, &dev_id1, &ino_id1); iso_stream_get_id(s2, &fs_id2, &dev_id2, &ino_id2); if (fs_id1 < fs_id2) { diff --git a/libisofs/stream.h b/libisofs/stream.h index 0b99b7e..bcbc3d0 100644 --- a/libisofs/stream.h +++ b/libisofs/stream.h @@ -82,8 +82,5 @@ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4, */ int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag); -/* ts A90502 */ -/* The former core of iso_file_src_cmp() */ -int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag); #endif /*STREAM_H_*/