New API call int iso_node_zf_by_magic() for marking pre-compressed data

file nodes which were originally produced by program mkzftree.
This commit is contained in:
Thomas Schmitt 2009-04-13 20:51:38 +02:00
parent 9a873ed693
commit 1f2fd259ae
5 changed files with 309 additions and 44 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -11,6 +11,8 @@
#include "node.h"
#include "stream.h"
#include "aaip_0_2.h"
#include "messages.h"
#include <stdlib.h>
#include <string.h>
@ -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;
}

View File

@ -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_*/

View File

@ -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;