From 1f2fd259ae00f2911ee6bd74c5188aa997662a16 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 13 Apr 2009 20:51:38 +0200 Subject: [PATCH] New API call int iso_node_zf_by_magic() for marking pre-compressed data file nodes which were originally produced by program mkzftree. --- libisofs/filters/zisofs.c | 79 +++++++++++++++++++++--- libisofs/libisofs.h | 88 +++++++++++++++++++------- libisofs/node.c | 126 ++++++++++++++++++++++++++++++++++++++ libisofs/node.h | 33 ++++++++++ libisofs/rockridge.c | 27 ++++---- 5 files changed, 309 insertions(+), 44 deletions(-) diff --git a/libisofs/filters/zisofs.c b/libisofs/filters/zisofs.c index 033d2ea..97286de 100644 --- a/libisofs/filters/zisofs.c +++ b/libisofs/filters/zisofs.c @@ -468,6 +468,29 @@ int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired) } +static +int ziso_parse_zisofs_head(IsoStream *stream, int *header_size_div4, + int *block_size_log2, uint32_t *uncompressed_size, + int flag) +{ + int ret; + char zisofs_head[16]; + + ret = iso_stream_read(stream, zisofs_head, 16); + if (ret < 0) + return ret; + *header_size_div4 = ((unsigned char *) zisofs_head)[12]; + *block_size_log2 = ((unsigned char *) zisofs_head)[13]; + if (ret != 16 || memcmp(zisofs_head, zisofs_magic, 8) != 0 || + *header_size_div4 < 4 || + *block_size_log2 < 15 || *block_size_log2 > 17) { + return ISO_ZISOFS_WRONG_INPUT; + } + *uncompressed_size = iso_read_lsb(((uint8_t *) zisofs_head) + 8, 4); + return 1; +} + + /* Note: A call with desired==0 directly after .open() only checks the file head and loads the uncompressed size from that head. */ @@ -484,7 +507,12 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired) size_t fill = 0; char *cbuf = buf; uLongf buf_len; + +#ifndef NIX + uint32_t uncompressed_size; +#else char zisofs_head[16]; +#endif if (stream == NULL) { return ISO_NULL_POINTER; @@ -502,6 +530,16 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired) while (1) { if (rng->state == 0) { /* Reading file header */ + +#ifndef NIX + ret = ziso_parse_zisofs_head(data->orig, &header_size, &bs_log2, + &uncompressed_size, 0); + if (ret < 0) + return (rng->error_ret = ret); + nstd->header_size_div4 = header_size; + header_size *= 4; + data->size = uncompressed_size; +#else ret = iso_stream_read(data->orig, zisofs_head, 16); if (ret < 0) return (rng->error_ret = ret); @@ -511,18 +549,25 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired) header_size < 16 || bs_log2 < 15 || bs_log2 > 17) { return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT); } + data->size = iso_read_lsb(((uint8_t *) zisofs_head) + 8, 4); + nstd->header_size_div4 = header_size / 4; +#endif /* NIX */ + + nstd->block_size_log2 = bs_log2; rng->block_size = 1 << bs_log2; if (header_size > 16) { /* Skip surplus header bytes */ + +/* >>> This must be a loop ret = iso_stream_read(data->orig, zisofs_head, header_size-16); if (ret < 0) return (rng->error_ret = ret); if (ret != header_size - 16) +*/ return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT); + + } - data->size = iso_read_lsb(((uint8_t *) zisofs_head) + 8, 4); - nstd->header_size_div4 = header_size / 4; - nstd->block_size_log2 = bs_log2; if (desired == 0) { return 0; @@ -1012,26 +1057,29 @@ int ziso_add_osiz_filter(IsoFile *file, uint8_t header_size_div4, -/* Determine stream type : 1=ziso , -1=osiz , 0=other +/* Determine stream type : 1=ziso , -1=osiz , 0=other , 2=ziso_by_content and eventual ZF field parameters + @param flag bit0= allow ziso_by_content which is based on content reading + bit1= do not inquire stream->class for filters */ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag) { + int ret, close_ret; ZisofsFilterStreamData *data; ZisofsComprStreamData *cnstd; ZisofsUncomprStreamData *unstd; *stream_type = 0; - if (stream->class == &ziso_stream_compress_class) { + if (stream->class == &ziso_stream_compress_class && !(flag & 2)) { *stream_type = 1; cnstd = stream->data; *header_size_div4 = 4; *block_size_log2 = ziso_block_size_log2; *uncompressed_size = cnstd->orig_size; return 1; - } else if(stream->class == &ziso_stream_uncompress_class) { + } else if(stream->class == &ziso_stream_uncompress_class && !(flag & 2)) { *stream_type = -1; data = stream->data; unstd = stream->data; @@ -1040,7 +1088,24 @@ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, *uncompressed_size = data->size; return 1; } - return 0; + if (!(flag & 1)) + return 0; + + ret = iso_stream_open(stream); + if (ret < 0) + return ret; + ret = ziso_parse_zisofs_head(stream, header_size_div4, + block_size_log2, uncompressed_size, 0); + if (ret == 1) { + *stream_type = 2; + } else { + ret = 0; + } + close_ret = iso_stream_close(stream); + if (close_ret < 0) + return close_ret; + + return ret; } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index ca592e9..a218856 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -1421,33 +1421,38 @@ int iso_write_opts_set_always_gmt(IsoWriteOpts *opts, int gmt); int iso_write_opts_set_output_charset(IsoWriteOpts *opts, const char *charset); /** - * Set the type of the image to create. Libisofs support two kind of images: - * stand-alone and appendable. + * Set the type of image creation in case there was already an existing + * image imported. Libisofs supports two types of creation: + * stand-alone and appended. * - * A stand-alone image is an image that is valid alone, and that can be - * mounted by its own. This is the kind of image you will want to create - * in most cases. A stand-alone image can be burned in an empty CD or DVD, - * or write to an .iso file for future burning or distribution. + * A stand-alone image is an image that does not need the old image any more + * for being mounted by the operating system or imported by libisofs. It may + * be written beginning with byte 0 of optical media or disk file objects. + * There will be no distinction between files from the old image and those + * which have been added by the new image generation. * - * On the other side, an appendable image is not self contained, it refers - * to serveral files that are stored outside the image. Its usage is for - * multisession discs, where you add data in a new session, while the - * previous session data can still be accessed. In those cases, the old - * data is not written again. Instead, the new image refers to it, and thus - * it's only valid when appended to the original. Note that in those cases - * the image will be written after the original, and thus you will want - * to use a ms_block greater than 0. + * On the other side, an appended image is not self contained. It may refer + * to files that stay stored in the imported existing image. + * This usage model is inspired by CD multi-session. It demands that the + * appended image is finally written to the same media resp. disk file + * as the imported image at an address behind the end of that imported image. + * The exact address may depend on media peculiarities and thus has to be + * announced by the application via iso_write_opts_set_ms_block(). + * The real address where the data will be written is under control of the + * consumer of the struct burn_source which takes the output of libisofs + * image generation. It may be the one announced to libisofs or an intermediate + * one. Nevertheless, the image will be readable only at the announced address. * - * Note that if you haven't import a previous image (by means of - * iso_image_import()), the image will always be a stand-alone image, as - * there is no previous data to refer to. + * If you have not imported a previous image by iso_image_import(), then the + * image will always be a stand-alone image, as there is no previous data to + * refer to. * - * @param appendable - * 1 to create an appendable image, 0 for an stand-alone one. + * @param append + * 1 to create an appended image, 0 for an stand-alone one. * * @since 0.6.2 */ -int iso_write_opts_set_appendable(IsoWriteOpts *opts, int appendable); +int iso_write_opts_set_appendable(IsoWriteOpts *opts, int append); /** * Set the start block of the image. It is supposed to be the lba where the @@ -1540,7 +1545,8 @@ int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start, /** * Create a burn_source and a thread which immediately begins to generate * the image. That burn_source can be used with libburn as a data source - * for a track. For its public declaration see libburn.h. + * for a track. A copy of its public declaration in libburn.h can be found + * further below in this text. * * If image generation shall be aborted by the application program, then * the .cancel() method of the burn_source must be called to end the @@ -4727,7 +4733,7 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, /* --------------------------- Filters in General -------------------------- */ /* - * A filter is an IsoStreams which uses another IsoStream as input. It gets + * A filter is an IsoStream which uses another IsoStream as input. It gets * attached to an IsoFile by specialized calls iso_file_add_*_filter() which * replace its current IsoStream by the filter stream which takes over the * current IsoStream as input. @@ -4745,6 +4751,10 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, * iso_file_add_zisofs_filter() * which may or may not be available depending on compile time settings and * installed software packages like libz. + * + * During image generation filters get not in effect if the original IsoStream + * is an "fsrc" stream based on a file in the loaded ISO image and if the + * image generation type is set to 1 by iso_write_opts_set_appendable(). */ /* ts A90328 */ @@ -4983,7 +4993,6 @@ struct iso_zisofs_ctrl { */ int iso_zisofs_set_params(struct iso_zisofs_ctrl *params, int flag); - /** * Get the current global parameters for zisofs filtering. * @param params @@ -4998,6 +5007,39 @@ int iso_zisofs_set_params(struct iso_zisofs_ctrl *params, int flag); int iso_zisofs_get_params(struct iso_zisofs_ctrl *params, int flag); +/* ts A90413 */ +/** + * Check for the given node or for its subtree whether the data file content + * effectively bears zisofs file headers and eventually mark the outcome + * by an xinfo data record if not already marked by a zisofs compressor filter. + * This does not install any filter but only a hint for image generation + * that the already compressed files shall get written with zisofs ZF entries. + * Use this if you insert the compressed reults of program mkzftree from disk + * into the image. + * @param node + * The node which shall be checked and eventually marked. + * @param flag + * Bitfield for control purposes, unused yet, submit 0 + * bit0= prepare for a run with iso_write_opts_set_appendable(,1). + * Take into account that files from the imported image + * do not get their content filtered. + * bit1= permission to overwrite existing zisofs_zf_info + * bit2= if no zisofs header is found: + * create xinfo with parameters which indicate no zisofs + * bit3= no tree recursion if node is a directory + * bit4= skip files which stem from the imported image + * @return + * 0= no zisofs data found + * 1= zf xinfo added + * 2= found existing zf xinfo and flag bit1 was not set + * 3= both encountered: 1 and 2 + * <0 means error + * + * @since 0.6.18 + */ +int iso_node_zf_by_magic(IsoNode *node, int flag); + + /* ------------------------------------------------------------------------- */ #ifdef LIBISOFS_WITHOUT_LIBBURN diff --git a/libisofs/node.c b/libisofs/node.c index 0f6ff2f..9bc977d 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -11,6 +11,8 @@ #include "node.h" #include "stream.h" #include "aaip_0_2.h" +#include "messages.h" + #include #include @@ -2115,3 +2117,127 @@ ex:; return st_mode; } + +/* Function to identify and manage ZF parameters. + * data is supposed to be a pointer to struct zisofs_zf_info + */ +int zisofs_zf_xinfo_func(void *data, int flag) +{ + if (flag & 1) { + free(data); + } + return 1; +} + + +/* Checks whether a file effectively bears a zisofs file header and eventually + * marks this by a struct zisofs_zf_info as xinfo of the file node. + * @param flag bit0= inquire the most original stream of the file + * bit1= permission to overwrite existing zisofs_zf_info + * bit2= if no zisofs header is found: + * create xinfo with parameters which indicate no zisofs + * @return 1= zf xinfo added, 0= no zisofs data found , + * 2= found existing zf xinfo and flag bit1 was not set + * <0 means error + */ +int iso_file_zf_by_magic(IsoFile *file, int flag) +{ + int ret, stream_type, header_size_div4, block_size_log2; + uint32_t uncompressed_size; + IsoStream *stream, *input_stream; + struct zisofs_zf_info *zf = NULL; + void *xipt; + + /* Intimate friendship with this function in filters/zisofs.c */ + int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, + int *header_size_div4, int *block_size_log2, + uint32_t *uncompressed_size, int flag); + + ret = iso_node_get_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, &xipt); + if (ret == 1) { + if (!(flag & 2)) + return 2; + ret = iso_node_remove_xinfo((IsoNode *) file, zisofs_zf_xinfo_func); + if (ret < 0) + return ret; + } + input_stream = stream = iso_file_get_stream(file); + while (flag & 1) { + input_stream = iso_stream_get_input_stream(stream, 0); + if (input_stream == NULL) + break; + stream = input_stream; + } + ret = ziso_is_zisofs_stream(stream, &stream_type, &header_size_div4, + &block_size_log2, &uncompressed_size, 3); + if (ret < 0) + return ret; + if (ret != 1 || stream_type != 2) { + if (flag & 4) + return 0; + header_size_div4 = 0; + block_size_log2 = 0; + uncompressed_size = 0; + } + zf = calloc(1, sizeof(struct zisofs_zf_info)); + if (zf == NULL) + return ISO_OUT_OF_MEM; + zf->uncompressed_size = uncompressed_size; + zf->header_size_div4 = header_size_div4; + zf->block_size_log2 = block_size_log2; + ret = iso_node_add_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, zf); + return ret; +} + + +/* API */ +int iso_node_zf_by_magic(IsoNode *node, int flag) +{ + int ret = 1, total_ret = 0, hflag; + IsoFile *file; + IsoNode *pos; + IsoDir *dir; + + if (node->type == LIBISO_FILE) + return iso_file_zf_by_magic((IsoFile *) node, flag); + if (node->type != LIBISO_DIR || (flag & 8)) + return 0; + + dir = (IsoDir *) node; + pos = dir->children; + while (pos) { + ret = 1; + if (pos->type == LIBISO_FILE) { + file = (IsoFile *) pos; + if ((flag & 16) && file->from_old_session) + return 0; + if (!((flag & 1) && file->from_old_session)) { + if (strncmp(file->stream->class->type, "ziso", 4) == 0) + return 1; /* The stream is enough of marking */ + if (strncmp(file->stream->class->type, "osiz", 4) == 0) { + if (flag & 2) + iso_node_remove_xinfo(pos, zisofs_zf_xinfo_func); + return 0; /* Will not be zisofs format */ + } + } + hflag = flag & ~6; + if ((flag & 1) && file->from_old_session) + hflag |= 1; + ret = iso_file_zf_by_magic(file, hflag); + } else if (pos->type == LIBISO_DIR) { + ret = iso_node_zf_by_magic(pos, flag); + } + if (ret < 0) { + total_ret = ret; + ret = iso_msg_submit(-1, ret, 0, NULL); + if (ret < 0) { + return ret; /* cancel due error threshold */ + } + } else if (total_ret >= 0) { + total_ret |= ret; + } + pos = pos->next; + } + return total_ret; +} + diff --git a/libisofs/node.h b/libisofs/node.h index d5de19e..62014dc 100644 --- a/libisofs/node.h +++ b/libisofs/node.h @@ -366,4 +366,37 @@ int iso_aa_lookup_attr(unsigned char *aa_string, char *name, size_t *value_length, char **value, int flag); +/** + * Function to identify and manage ZF parameters which do not stem from ZF + * fields (those are known to the FileSource) and do not stem from filters + * ("ziso" knows them globally, "osiz" knows them individually) but rather + * from an inspection of the file content header for zisofs magic number and + * plausible parameters. + * The parameters get attached in struct zisofs_zf_info as xinfo to an IsoNode. + */ +int zisofs_zf_xinfo_func(void *data, int flag); + +/** + * Parameter structure which is to be managed by zisofs_zf_xinfo_func. + */ +struct zisofs_zf_info { + uint32_t uncompressed_size; + uint8_t header_size_div4; + uint8_t block_size_log2; +}; + +/** + * Checks whether a file effectively bears a zisofs file header and eventually + * marks this by a struct zisofs_zf_info as xinfo of the file node. + * @param flag bit0= inquire the most original stream of the file + * bit1= permission to overwrite existing zisofs_zf_info + * bit2= if no zisofs header is found: + create xinfo with parameters which indicate no zisofs + * @return 1= zf xinfo added, 0= no zisofs data found , + * 2= found existing zf xinfo and flag bit1 was not set + * <0 means error + */ +int iso_file_zf_by_magic(IsoFile *file, int flag); + + #endif /*LIBISO_NODE_H_*/ diff --git a/libisofs/rockridge.c b/libisofs/rockridge.c index 117e8ba..e4924c7 100644 --- a/libisofs/rockridge.c +++ b/libisofs/rockridge.c @@ -809,6 +809,8 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info, IsoStream *stream = NULL, *input_stream, *last_stream, *first_stream; IsoStream *first_filter = NULL; IsoFile *file; + void *xipt; + struct zisofs_zf_info *zf; /* Intimate friendship with this function in filters/zisofs.c */ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, @@ -867,22 +869,19 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info, if (ret == 1 && header_size_div4 > 0) do_zf = 1; } - -#ifdef Libisofs_not_yeT - if (t->zisofs_magic && (flag & 1) && !do_zf) { - - if (will_copy) { - stream = last_stream; - } else { - stream = first_stream; + if (!do_zf) { + /* Look for an xinfo mark of a zisofs header */ + ret = iso_node_get_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, + &xipt); + if (ret == 1) { + zf = xipt; + header_size_div4 = zf->header_size_div4; + block_size_log2 = zf->block_size_log2; + uncompressed_size = zf->uncompressed_size; + if (header_size_div4 > 0) + do_zf = 1; } - /* >>> open stream via temporary osiz filter and read 0 bytes. - If no error: do_zf = 1; */; - /* >>> obtain - header_size_div4, block_size_log2, uncompressed_size */; - /* >>> record info for runs with !(flag&1) : as n->node->xinfo */; } -#endif if (!do_zf) return 2;