Implemented a zisofs uncompression filter.

This commit is contained in:
Thomas Schmitt 2009-04-10 12:16:41 +02:00
parent a809a87eef
commit ce7a5c810f
5 changed files with 315 additions and 73 deletions

View File

@ -29,6 +29,10 @@ The file header has this layout (quoted from zisofs-tools-1.0.8/mkzftree.c):
So its size is 16. So its size is 16.
7.3.1 means little endian 4-byte words. 7.1.1. means unsigned single bytes. 7.3.1 means little endian 4-byte words. 7.1.1. means unsigned single bytes.
Readers shall be able to handle log2(block_size) values 15, 16 and 17
i.e. block sizes 32 kB, 64 kB, and 128 kB.
Block Pointers Block Pointers
There are ceil(input_size / block_size) input resp. output blocks. There are ceil(input_size / block_size) input resp. output blocks.
@ -43,6 +47,7 @@ So there are ceil(input_size / block_size) + 1 block pointers.
They are stored as an array of 4-byte values which are in ISO 9660:7.3.1 format They are stored as an array of 4-byte values which are in ISO 9660:7.3.1 format
directly after the file header, i.e. beginning at byte 16. directly after the file header, i.e. beginning at byte 16.
Data Part Data Part
The data part begins immediately after the pointer array. In principle it The data part begins immediately after the pointer array. In principle it
@ -98,7 +103,7 @@ Its fields are:
ISO 9660:7.3.3 means 4-byte word in both byte orders, first little endian, then ISO 9660:7.3.3 means 4-byte word in both byte orders, first little endian, then
big endian. big endian.
Example (uncompressed file size = 1,234,567 bytes): Example (block size 32 kB, uncompressed file size = 1,234,567 bytes):
{ 'Z', "F', 16, 1, 'p', 'z', 16, 15, { 'Z', "F', 16, 1, 'p', 'z', 16, 15,
0x87, 0xD6, 0x12, 0x00, 0x00, 0x12, 0xD6, 0x87 } 0x87, 0xD6, 0x12, 0x00, 0x00, 0x12, 0xD6, 0x87 }

View File

@ -22,7 +22,7 @@
#define ISO_FILTER_EXTERNAL_DEV_ID 2 #define ISO_FILTER_EXTERNAL_DEV_ID 2
/* libisofs/filters/zisofs.c */ /* libisofs/filters/zisofs.c */
#define ISO_FILTER_ZISOFSL_DEV_ID 3 #define ISO_FILTER_ZISOFS_DEV_ID 3
typedef struct filter_context FilterContext; typedef struct filter_context FilterContext;

View File

@ -66,6 +66,8 @@ typedef struct
off_t in_counter; off_t in_counter;
off_t out_counter; off_t out_counter;
int error_ret;
} ZisofsFilterRuntime; } ZisofsFilterRuntime;
@ -108,6 +110,7 @@ int ziso_running_new(ZisofsFilterRuntime **running, int flag)
o->block_counter = 0; o->block_counter = 0;
o->in_counter = 0; o->in_counter = 0;
o->out_counter = 0; o->out_counter = 0;
o->error_ret = 0;
if (flag & 1) if (flag & 1)
return 1; return 1;
@ -169,6 +172,8 @@ static ino_t ziso_ino_id = 0;
* Methods for the IsoStreamIface of an External Filter object. * Methods for the IsoStreamIface of an External Filter object.
*/ */
static
int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired);
/* /*
* @param flag bit0= original stream is not open * @param flag bit0= original stream is not open
@ -189,6 +194,13 @@ int ziso_stream_close_flag(IsoStream *stream, int flag)
ziso_running_destroy(&(data->running), 0); ziso_running_destroy(&(data->running), 0);
if (flag & 1) if (flag & 1)
return 1; return 1;
if (stream->class->read == ziso_stream_uncompress &&
data->block_pointers != NULL) {
/* No permanent block pointers needed for uncompression */
free(data->block_pointers);
data->block_pointers = NULL;
}
return iso_stream_close(data->orig); return iso_stream_close(data->orig);
} }
@ -224,7 +236,8 @@ int ziso_stream_open_flag(IsoStream *stream, int flag)
stream->class->get_size(stream); stream->class->get_size(stream);
} }
ret = ziso_running_new(&running, 0); ret = ziso_running_new(&running,
stream->class->read == ziso_stream_uncompress);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -246,20 +259,18 @@ int ziso_stream_open(IsoStream *stream)
static static
int ziso_stream_read(IsoStream *stream, void *buf, size_t desired) int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired)
{ {
#ifdef Libisofs_with_zliB
int ret, todo, i; int ret, todo, i;
ZisofsFilterStreamData *data; ZisofsFilterStreamData *data;
ZisofsFilterRuntime *rng; ZisofsFilterRuntime *rng;
size_t fill = 0; size_t fill = 0;
off_t orig_size, next_pt; off_t orig_size, next_pt;
char *cbuf = buf; char *cbuf = buf;
#ifdef Libisofs_with_zliB
uLongf buf_len; uLongf buf_len;
#else
unsigned long buf_len;
#endif
if (stream == NULL) { if (stream == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
@ -269,6 +280,9 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
if (rng == NULL) { if (rng == NULL) {
return ISO_FILE_NOT_OPENED; return ISO_FILE_NOT_OPENED;
} }
if (rng->error_ret < 0) {
return rng->error_ret;
}
while (1) { while (1) {
if (rng->state == 0) { if (rng->state == 0) {
@ -278,11 +292,7 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
memcpy(rng->block_buffer, zisofs_magic, 8); memcpy(rng->block_buffer, zisofs_magic, 8);
orig_size = iso_stream_get_size(data->orig); orig_size = iso_stream_get_size(data->orig);
if (orig_size > 4294967295.0) { if (orig_size > 4294967295.0) {
return (rng->error_ret = ISO_ZISOFS_TOO_LARGE);
/* >>> cannot compress file >= 4 GiB to zisofs */;
/* <<< need better error code (or fallback strategy ?) */
return ISO_FILE_READ_ERROR;
} }
data->orig_size = orig_size; data->orig_size = orig_size;
iso_lsb((unsigned char *) (rng->block_buffer + 8), iso_lsb((unsigned char *) (rng->block_buffer + 8),
@ -304,13 +314,13 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
/* Initialize block pointer writing */ /* Initialize block pointer writing */
rng->block_pointer_rpos = 0; rng->block_pointer_rpos = 0;
rng->block_pointer_fill = data->orig_size / rng->block_size rng->block_pointer_fill = data->orig_size / rng->block_size
+ 1 + !!(orig_size % rng->block_size); + 1 + !!(data->orig_size % rng->block_size);
if (data->block_pointers == NULL) { if (data->block_pointers == NULL) {
/* On the first pass, create pointer array with all 0s */ /* On the first pass, create pointer array with all 0s */
data->block_pointers = calloc(rng->block_pointer_fill, 4); data->block_pointers = calloc(rng->block_pointer_fill, 4);
if (data->block_pointers == NULL) { if (data->block_pointers == NULL) {
rng->block_pointer_fill = 0; rng->block_pointer_fill = 0;
return ISO_OUT_OF_MEM; return (rng->error_ret = ISO_OUT_OF_MEM);
} }
} }
} }
@ -335,21 +345,16 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
} }
} }
if (rng->state == 2 && rng->buffer_rpos >= rng->buffer_fill) { if (rng->state == 2 && rng->buffer_rpos >= rng->buffer_fill) {
/* >>> Delivering data blocks */; /* Delivering data blocks */;
ret = iso_stream_read(data->orig, rng->read_buffer, ret = iso_stream_read(data->orig, rng->read_buffer,
rng->block_size); rng->block_size);
if (ret > 0) { if (ret > 0) {
rng->in_counter += ret; rng->in_counter += ret;
if (rng->in_counter > data->orig_size) { if (rng->in_counter > data->orig_size) {
/* Input size became larger */
/* >>> Input size overflow */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
/* <<< need better error code */
return ISO_FILE_READ_ERROR;
} }
/* Check whether all 0 : represent as 0-length block */; /* Check whether all 0 : represent as 0-length block */;
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
if (rng->read_buffer[i]) if (rng->read_buffer[i])
@ -358,45 +363,28 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
buf_len = 0; buf_len = 0;
} else { } else {
buf_len = rng->buffer_size; buf_len = rng->buffer_size;
#ifdef Libisofs_with_zliB
ret = compress2((Bytef *) rng->block_buffer, &buf_len, ret = compress2((Bytef *) rng->block_buffer, &buf_len,
(Bytef *) rng->read_buffer, (uLong) ret, 9); (Bytef *) rng->read_buffer, (uLong) ret, 9);
if (ret != Z_OK) { if (ret != Z_OK) {
#else return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
{
#endif
/* >>> compression failed */
/* <<< need better error code */
return ISO_FILE_READ_ERROR;
} }
} }
rng->buffer_fill = buf_len; rng->buffer_fill = buf_len;
rng->buffer_rpos = 0; rng->buffer_rpos = 0;
next_pt = data->block_pointers[rng->block_counter] + buf_len; next_pt = data->block_pointers[rng->block_counter] + buf_len;
/* >>> check for data->size overflow */;
if (data->size >= 0 && next_pt > data->size) { if (data->size >= 0 && next_pt > data->size) {
/* Compression yields more bytes than on first run */
/* >>> Compression yields more bytes than on first run */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
/* <<< need better error code */
return ISO_FILE_READ_ERROR;
} }
/* >>> record resp. check block pointer */; /* Record resp. check block pointer */
rng->block_counter++; rng->block_counter++;
if (data->block_pointers[rng->block_counter] > 0) { if (data->block_pointers[rng->block_counter] > 0) {
/* >>> check */;
if (next_pt != data->block_pointers[rng->block_counter] ) { if (next_pt != data->block_pointers[rng->block_counter] ) {
/* block pointers mismatch , content has changed */
/* >>> block pointers mismatch , content has changed */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
/* <<< need better error code */
return ISO_FILE_READ_ERROR;
} }
} else { } else {
data->block_pointers[rng->block_counter] = next_pt; data->block_pointers[rng->block_counter] = next_pt;
@ -404,9 +392,13 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
} else if (ret == 0) { } else if (ret == 0) {
rng->state = 3; rng->state = 3;
if (rng->in_counter != data->orig_size) {
/* Input size shrunk */
return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
}
return fill; return fill;
} else } else
return ret; return (rng->error_ret = ret);
if (rng->buffer_fill == 0) { if (rng->buffer_fill == 0) {
continue; continue;
} }
@ -429,6 +421,175 @@ int ziso_stream_read(IsoStream *stream, void *buf, size_t desired)
} }
} }
return ISO_FILE_READ_ERROR; /* should never be hit */ return ISO_FILE_READ_ERROR; /* should never be hit */
#else
return ISO_ZLIB_NOT_ENABLED;
#endif
}
/* Note: A call with desired==0 directly after .open() only checks the file
head and loads the uncompressed size from that head.
*/
static
int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
{
#ifdef Libisofs_with_zliB
int ret, todo, i, header_size, bs_log2, block_max = 1;
ZisofsFilterStreamData *data;
ZisofsFilterRuntime *rng;
size_t fill = 0;
char *cbuf = buf;
uLongf buf_len;
char zisofs_head[16];
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
rng= data->running;
if (rng == NULL) {
return ISO_FILE_NOT_OPENED;
}
if (rng->error_ret < 0) {
return rng->error_ret;
}
while (1) {
if (rng->state == 0) {
/* Reading file header */
ret = iso_stream_read(data->orig, zisofs_head, 16);
if (ret < 0)
return (rng->error_ret = ret);
header_size = ((unsigned char *) zisofs_head)[12] * 4;
bs_log2 = ((unsigned char *) zisofs_head)[13];
if (ret != 16 || memcmp(zisofs_head, zisofs_magic, 8) != 0 ||
header_size < 16 || bs_log2 < 15 || bs_log2 > 17) {
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
}
rng->block_size = 1 << bs_log2;
if (header_size > 16) {
/* Skip surplus header bytes */
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);
if (desired == 0) {
return 0;
}
/* Create and read pointer array */
rng->block_pointer_rpos = 0;
rng->block_pointer_fill = data->size / rng->block_size
+ 1 + !!(data->size % rng->block_size);
data->block_pointers = calloc(rng->block_pointer_fill, 4);
if (data->block_pointers == NULL) {
rng->block_pointer_fill = 0;
return (rng->error_ret = ISO_OUT_OF_MEM);
}
ret = iso_stream_read(data->orig, data->block_pointers,
rng->block_pointer_fill * 4);
if (ret < 0)
return (rng->error_ret = ret);
if (ret != rng->block_pointer_fill * 4)
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
for (i = 0; i < rng->block_pointer_fill; i++) {
data->block_pointers[i] =
iso_read_lsb((uint8_t *) (data->block_pointers + i), 4);
if (i > 0)
if (data->block_pointers[i] - data->block_pointers[i - 1]
> block_max)
block_max = data->block_pointers[i]
- data->block_pointers[i - 1];
}
rng->read_buffer = calloc(block_max, 1);
rng->block_buffer = calloc(rng->block_size, 1);
if (rng->read_buffer == NULL || rng->block_buffer == NULL)
return (rng->error_ret = ISO_OUT_OF_MEM);
rng->state = 2; /* block pointers are read */
rng->buffer_fill = rng->buffer_rpos = 0;
}
if (rng->state == 2 && rng->buffer_rpos >= rng->buffer_fill) {
/* Delivering data blocks */;
i = ++(rng->block_pointer_rpos);
if (i >= rng->block_pointer_fill) {
/* More data blocks than announced */
return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
}
todo = data->block_pointers[i] - data->block_pointers[i- 1];
if (todo == 0) {
memset(rng->read_buffer, 0, rng->block_size);
rng->buffer_fill = rng->block_size;
if (rng->in_counter + rng->buffer_fill > data->size &&
i == rng->block_pointer_fill - 1)
rng->buffer_fill = data->size - rng->in_counter;
rng->in_counter += rng->buffer_fill;
} else {
ret = iso_stream_read(data->orig, rng->read_buffer, todo);
if (ret > 0) {
rng->in_counter += ret;
buf_len = rng->block_size;
ret = uncompress((Bytef *) rng->block_buffer, &buf_len,
(Bytef *) rng->read_buffer, (uLong) ret);
if (ret != Z_OK)
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
rng->buffer_fill = buf_len;
if (buf_len < rng->block_size &&
i != rng->block_pointer_fill - 1)
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
} else if(ret == 0) {
rng->state = 3;
if (rng->out_counter != data->size) {
/* Input size shrunk */
return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
}
return fill;
} else
return (rng->error_ret = ret);
}
rng->buffer_rpos = 0;
if (rng->out_counter + rng->buffer_fill > data->size) {
/* Uncompression yields more bytes than announced by header */
return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
}
}
if (rng->state == 3 && rng->buffer_rpos >= rng->buffer_fill) {
return 0; /* EOF */
}
/* Transfer from rng->block_buffer to buf */
todo = desired - fill;
if (todo > rng->buffer_fill - rng->buffer_rpos)
todo = rng->buffer_fill - rng->buffer_rpos;
memcpy(cbuf + fill, rng->block_buffer + rng->buffer_rpos, todo);
fill += todo;
rng->buffer_rpos += todo;
rng->out_counter += todo;
if (fill >= desired) {
return fill;
}
}
return (rng->error_ret = ISO_FILE_READ_ERROR); /* should never be hit */
#else
return ISO_ZLIB_NOT_ENABLED;
#endif
} }
@ -455,12 +616,19 @@ off_t ziso_stream_get_size(IsoStream *stream)
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
if (stream->class->read == ziso_stream_uncompress) {
/* It is enough to read the header part of a compressed file */
ret = ziso_stream_uncompress(stream, buf, 0);
count = data->size;
} else {
/* The size of the compression result has to be counted */
while (1) { while (1) {
ret = ziso_stream_read(stream, buf, bufsize); ret = stream->class->read(stream, buf, bufsize);
if (ret <= 0) if (ret <= 0)
break; break;
count += ret; count += ret;
} }
}
ret_close = ziso_stream_close(stream); ret_close = ziso_stream_close(stream);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -488,7 +656,7 @@ void ziso_stream_get_id(IsoStream *stream, unsigned int *fs_id,
data = stream->data; data = stream->data;
*fs_id = ISO_FILTER_FS_ID; *fs_id = ISO_FILTER_FS_ID;
*dev_id = ISO_FILTER_ZISOFSL_DEV_ID; *dev_id = ISO_FILTER_ZISOFS_DEV_ID;
*ino_id = data->id; *ino_id = data->id;
} }
@ -534,13 +702,28 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
} }
IsoStreamIface ziso_stream_class = { IsoStreamIface ziso_stream_compress_class = {
2, 2,
"ziso", "ziso",
ziso_stream_open, ziso_stream_open,
ziso_stream_close, ziso_stream_close,
ziso_stream_get_size, ziso_stream_get_size,
ziso_stream_read, ziso_stream_compress,
ziso_stream_is_repeatable,
ziso_stream_get_id,
ziso_stream_free,
ziso_update_size,
ziso_get_input_stream
};
IsoStreamIface ziso_stream_uncompress_class = {
2,
"osiz",
ziso_stream_open,
ziso_stream_close,
ziso_stream_get_size,
ziso_stream_uncompress,
ziso_stream_is_repeatable, ziso_stream_is_repeatable,
ziso_stream_get_id, ziso_stream_get_id,
ziso_stream_free, ziso_stream_free,
@ -556,13 +739,12 @@ void ziso_filter_free(FilterContext *filter)
} }
/* To be called by iso_file_add_filter(). /*
* The FilterContext input parameter is not furtherly needed for the * @param flag bit1= Install a decompression filter
* emerging IsoStream.
*/ */
static static
int ziso_filter_get_filter(FilterContext *filter, IsoStream *original, int ziso_filter_get_filter(FilterContext *filter, IsoStream *original,
IsoStream **filtered) IsoStream **filtered, int flag)
{ {
IsoStream *str; IsoStream *str;
ZisofsFilterStreamData *data; ZisofsFilterStreamData *data;
@ -594,7 +776,11 @@ int ziso_filter_get_filter(FilterContext *filter, IsoStream *original,
str->refcount = 1; str->refcount = 1;
str->data = data; str->data = data;
str->class = &ziso_stream_class; if (flag & 2) {
str->class = &ziso_stream_uncompress_class;
} else {
str->class = &ziso_stream_compress_class;
}
*filtered = str; *filtered = str;
@ -602,10 +788,30 @@ int ziso_filter_get_filter(FilterContext *filter, IsoStream *original,
} }
/* To be called by iso_file_add_filter().
* The FilterContext input parameter is not furtherly needed for the
* emerging IsoStream.
*/
static
int ziso_filter_get_compressor(FilterContext *filter, IsoStream *original,
IsoStream **filtered)
{
return ziso_filter_get_filter(filter, original, filtered, 0);
}
static
int ziso_filter_get_uncompressor(FilterContext *filter, IsoStream *original,
IsoStream **filtered)
{
return ziso_filter_get_filter(filter, original, filtered, 2);
}
/* Produce a parameter object suitable for iso_file_add_filter(). /* Produce a parameter object suitable for iso_file_add_filter().
* It may be disposed by free() after all those calls are made. * It may be disposed by free() after all those calls are made.
* *
* This is quite a dummy as it dows not carry individual data. * This is quite a dummy as it does not carry individual data.
* @param flag bit1= Install a decompression filter
*/ */
static static
int ziso_create_context(FilterContext **filter, int flag) int ziso_create_context(FilterContext **filter, int flag)
@ -620,14 +826,18 @@ int ziso_create_context(FilterContext **filter, int flag)
f->version = 0; f->version = 0;
f->data = NULL; f->data = NULL;
f->free = ziso_filter_free; f->free = ziso_filter_free;
f->get_filter = ziso_filter_get_filter; if (flag & 2)
f->get_filter = ziso_filter_get_uncompressor;
else
f->get_filter = ziso_filter_get_compressor;
return ISO_SUCCESS; return ISO_SUCCESS;
} }
/* /*
* @param flag bit0= if_block_reduction rather than if_reduction * @param flag bit0= if_block_reduction rather than if_reduction
* >>> bit1= Install a decompression filter * bit1= Install a decompression filter
* bit2= only inquire availability of zisofs filtering
*/ */
int iso_file_add_zisofs_filter(IsoFile *file, int flag) int iso_file_add_zisofs_filter(IsoFile *file, int flag)
{ {
@ -639,15 +849,20 @@ int iso_file_add_zisofs_filter(IsoFile *file, int flag)
IsoStream *stream; IsoStream *stream;
off_t original_size = 0, filtered_size = 0; off_t original_size = 0, filtered_size = 0;
if (flag & 4)
return 2;
original_size = iso_file_get_size(file); original_size = iso_file_get_size(file);
if (!(flag & 2)) {
if (original_size <= 0) { if (original_size <= 0) {
return 2; return 2;
} }
if (original_size > 4294967295.0) { if (original_size > 4294967295.0) {
return ISO_ZISOFS_TOO_LARGE; return ISO_ZISOFS_TOO_LARGE;
} }
}
ret = ziso_create_context(&f, 0); ret = ziso_create_context(&f, flag & 2);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -663,8 +878,8 @@ int iso_file_add_zisofs_filter(IsoFile *file, int flag)
iso_file_remove_filter(file, 0); iso_file_remove_filter(file, 0);
return filtered_size; return filtered_size;
} }
if ((filtered_size >= original_size && !(flag & 1)) || if (((filtered_size >= original_size && !(flag & 1)) ||
filtered_size / 2048 >= original_size / 2048){ filtered_size / 2048 >= original_size / 2048) && !(flag & 2)){
ret = iso_file_remove_filter(file, 0); ret = iso_file_remove_filter(file, 0);
if (ret < 0) { if (ret < 0) {
return ret; return ret;

View File

@ -782,6 +782,8 @@ struct IsoStream_Iface
* "mem " -> Read from memory * "mem " -> Read from memory
* "boot" -> Boot catalog * "boot" -> Boot catalog
* "extf" -> External filter program * "extf" -> External filter program
* "ziso" -> zisofs compression
* "osiz" -> zisofs uncompression
* "user" -> User supplied stream * "user" -> User supplied stream
*/ */
char type[4]; char type[4];
@ -4704,6 +4706,18 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
/** Cannot apply zisofs filter to file >= 4 GiB (FAILURE, HIGH, -346) */ /** Cannot apply zisofs filter to file >= 4 GiB (FAILURE, HIGH, -346) */
#define ISO_ZISOFS_TOO_LARGE 0xE830FEA6 #define ISO_ZISOFS_TOO_LARGE 0xE830FEA6
/* ts A90409 */
/** Filter input differs from previous run (FAILURE, HIGH, -347) */
#define ISO_FILTER_WRONG_INPUT 0xE830FEA5
/* ts A90409 */
/** zlib compression/decompression error (FAILURE, HIGH, -348) */
#define ISO_ZLIB_COMPR_ERR 0xE830FEA4
/* ts A90409 */
/** Input stream is not in zisofs format (FAILURE, HIGH, -349) */
#define ISO_ZISOFS_WRONG_INPUT 0xE830FEA3
/* --------------------------- Filters in General -------------------------- */ /* --------------------------- Filters in General -------------------------- */
@ -4897,8 +4911,10 @@ int iso_stream_get_external_filter(IsoStream *stream,
* bit0= Do not install filter if the number of output blocks is * bit0= Do not install filter if the number of output blocks is
* not smaller than the number of input blocks. Block size is 2048. * not smaller than the number of input blocks. Block size is 2048.
* bit1= Install a decompression filter rather than one for compression. * bit1= Install a decompression filter rather than one for compression.
* bit2= Only inquire availability of zisofs filtering. file may be NULL.
* If available return 2, else return error.
* @return * @return
* 1 on success, 2 if filter installation revoked * 1 on success, 2 if filter available but installation revoked
* <0 on error, e.g. ISO_ZLIB_NOT_ENABLED * <0 on error, e.g. ISO_ZLIB_NOT_ENABLED
* *
* @since 0.6.18 * @since 0.6.18

View File

@ -253,6 +253,12 @@ const char *iso_error_to_msg(int errcode)
return "Use of zlib was not enabled at compile time"; return "Use of zlib was not enabled at compile time";
case ISO_ZISOFS_TOO_LARGE: case ISO_ZISOFS_TOO_LARGE:
return "Cannot apply zisofs filter to file >= 4 GiB"; return "Cannot apply zisofs filter to file >= 4 GiB";
case ISO_FILTER_WRONG_INPUT:
return "Filter input differs from previous run";
case ISO_ZLIB_COMPR_ERR:
return "zlib compression/decompression error";
case ISO_ZISOFS_WRONG_INPUT:
return "Input stream is not in zisofs format";
default: default:
return "Unknown error"; return "Unknown error";
} }