mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Update to add in support for AZIO.
AZIO differs in that it uses mysys methods and removes all of the malloc calls.
This commit is contained in:
@ -2413,7 +2413,7 @@ MYSQL_STORAGE_ENGINE(berkeley,,berkeley-db,,,,storage/bdb,,,[
|
|||||||
MYSQL_SETUP_BERKELEY_DB
|
MYSQL_SETUP_BERKELEY_DB
|
||||||
])
|
])
|
||||||
MYSQL_STORAGE_ENGINE(example)
|
MYSQL_STORAGE_ENGINE(example)
|
||||||
MYSQL_STORAGE_ENGINE(archive)
|
MYSQL_STORAGE_ENGINE(archive,,,,,,storage/archive)
|
||||||
MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
|
MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
|
||||||
MYSQL_STORAGE_ENGINE(blackhole)
|
MYSQL_STORAGE_ENGINE(blackhole)
|
||||||
MYSQL_STORAGE_ENGINE(federated)
|
MYSQL_STORAGE_ENGINE(federated)
|
||||||
@ -2535,6 +2535,7 @@ AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
|
|||||||
AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
|
AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
|
||||||
strings/Makefile regex/Makefile storage/Makefile storage/heap/Makefile dnl
|
strings/Makefile regex/Makefile storage/Makefile storage/heap/Makefile dnl
|
||||||
storage/myisam/Makefile storage/myisammrg/Makefile dnl
|
storage/myisam/Makefile storage/myisammrg/Makefile dnl
|
||||||
|
storage/archive/Makefile dnl
|
||||||
os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
|
os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
|
||||||
man/Makefile BUILD/Makefile vio/Makefile dnl
|
man/Makefile BUILD/Makefile vio/Makefile dnl
|
||||||
libmysql/Makefile client/Makefile dnl
|
libmysql/Makefile client/Makefile dnl
|
||||||
|
@ -81,6 +81,7 @@ sql_yacc.cc sql_yacc.h: $(top_srcdir)/sql/sql_yacc.yy
|
|||||||
INC_LIB= $(top_builddir)/regex/libregex.a \
|
INC_LIB= $(top_builddir)/regex/libregex.a \
|
||||||
$(top_builddir)/storage/myisam/libmyisam.a \
|
$(top_builddir)/storage/myisam/libmyisam.a \
|
||||||
$(top_builddir)/storage/myisammrg/libmyisammrg.a \
|
$(top_builddir)/storage/myisammrg/libmyisammrg.a \
|
||||||
|
$(top_builddir)/storage/archive/libarchive.a \
|
||||||
$(top_builddir)/storage/heap/libheap.a \
|
$(top_builddir)/storage/heap/libheap.a \
|
||||||
$(top_builddir)/mysys/libmysys.a \
|
$(top_builddir)/mysys/libmysys.a \
|
||||||
$(top_builddir)/strings/libmystrings.a \
|
$(top_builddir)/strings/libmystrings.a \
|
||||||
|
@ -32,6 +32,7 @@ bin_PROGRAMS = mysql_tzinfo_to_sql
|
|||||||
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
|
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
|
||||||
LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
|
LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
|
||||||
$(top_builddir)/storage/myisammrg/libmyisammrg.a \
|
$(top_builddir)/storage/myisammrg/libmyisammrg.a \
|
||||||
|
$(top_builddir)/storage/archive/libarchive.a \
|
||||||
$(top_builddir)/storage/heap/libheap.a \
|
$(top_builddir)/storage/heap/libheap.a \
|
||||||
$(top_builddir)/vio/libvio.a \
|
$(top_builddir)/vio/libvio.a \
|
||||||
$(top_builddir)/mysys/libmysys.a \
|
$(top_builddir)/mysys/libmysys.a \
|
||||||
|
@ -30,13 +30,13 @@
|
|||||||
a storage engine without indexes that could compress data very well.
|
a storage engine without indexes that could compress data very well.
|
||||||
So, welcome to a completely compressed storage engine. This storage
|
So, welcome to a completely compressed storage engine. This storage
|
||||||
engine only does inserts. No replace, deletes, or updates. All reads are
|
engine only does inserts. No replace, deletes, or updates. All reads are
|
||||||
complete table scans. Compression is done through gzip (bzip compresses
|
complete table scans. Compression is done through azip (bzip compresses
|
||||||
better, but only marginally, if someone asks I could add support for
|
better, but only marginally, if someone asks I could add support for
|
||||||
it too, but beaware that it costs a lot more in CPU time then gzip).
|
it too, but beaware that it costs a lot more in CPU time then azip).
|
||||||
|
|
||||||
We keep a file pointer open for each instance of ha_archive for each read
|
We keep a file pointer open for each instance of ha_archive for each read
|
||||||
but for writes we keep one open file handle just for that. We flush it
|
but for writes we keep one open file handle just for that. We flush it
|
||||||
only if we have a read occur. gzip handles compressing lots of records
|
only if we have a read occur. azip handles compressing lots of records
|
||||||
at once much better then doing lots of little records between writes.
|
at once much better then doing lots of little records between writes.
|
||||||
It is possible to not lock on writes but this would then mean we couldn't
|
It is possible to not lock on writes but this would then mean we couldn't
|
||||||
handle bulk inserts as well (that is if someone was trying to read at
|
handle bulk inserts as well (that is if someone was trying to read at
|
||||||
@ -84,7 +84,7 @@
|
|||||||
Add truncate table command.
|
Add truncate table command.
|
||||||
Implement versioning, should be easy.
|
Implement versioning, should be easy.
|
||||||
Allow for errors, find a way to mark bad rows.
|
Allow for errors, find a way to mark bad rows.
|
||||||
Talk to the gzip guys, come up with a writable format so that updates are doable
|
Talk to the azip guys, come up with a writable format so that updates are doable
|
||||||
without switching to a block method.
|
without switching to a block method.
|
||||||
Add optional feature so that rows can be flushed at interval (which will cause less
|
Add optional feature so that rows can be flushed at interval (which will cause less
|
||||||
compression but may speed up ordered searches).
|
compression but may speed up ordered searches).
|
||||||
@ -256,15 +256,15 @@ ha_archive::ha_archive(TABLE_SHARE *table_arg)
|
|||||||
/*
|
/*
|
||||||
This method reads the header of a datafile and returns whether or not it was successful.
|
This method reads the header of a datafile and returns whether or not it was successful.
|
||||||
*/
|
*/
|
||||||
int ha_archive::read_data_header(gzFile file_to_read)
|
int ha_archive::read_data_header(azio_stream *file_to_read)
|
||||||
{
|
{
|
||||||
uchar data_buffer[DATA_BUFFER_SIZE];
|
uchar data_buffer[DATA_BUFFER_SIZE];
|
||||||
DBUG_ENTER("ha_archive::read_data_header");
|
DBUG_ENTER("ha_archive::read_data_header");
|
||||||
|
|
||||||
if (gzrewind(file_to_read) == -1)
|
if (azrewind(file_to_read) == -1)
|
||||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||||
|
|
||||||
if (gzread(file_to_read, data_buffer, DATA_BUFFER_SIZE) != DATA_BUFFER_SIZE)
|
if (azread(file_to_read, data_buffer, DATA_BUFFER_SIZE) != DATA_BUFFER_SIZE)
|
||||||
DBUG_RETURN(errno ? errno : -1);
|
DBUG_RETURN(errno ? errno : -1);
|
||||||
|
|
||||||
DBUG_PRINT("ha_archive::read_data_header", ("Check %u", data_buffer[0]));
|
DBUG_PRINT("ha_archive::read_data_header", ("Check %u", data_buffer[0]));
|
||||||
@ -280,7 +280,7 @@ int ha_archive::read_data_header(gzFile file_to_read)
|
|||||||
/*
|
/*
|
||||||
This method writes out the header of a datafile and returns whether or not it was successful.
|
This method writes out the header of a datafile and returns whether or not it was successful.
|
||||||
*/
|
*/
|
||||||
int ha_archive::write_data_header(gzFile file_to_write)
|
int ha_archive::write_data_header(azio_stream *file_to_write)
|
||||||
{
|
{
|
||||||
uchar data_buffer[DATA_BUFFER_SIZE];
|
uchar data_buffer[DATA_BUFFER_SIZE];
|
||||||
DBUG_ENTER("ha_archive::write_data_header");
|
DBUG_ENTER("ha_archive::write_data_header");
|
||||||
@ -288,7 +288,7 @@ int ha_archive::write_data_header(gzFile file_to_write)
|
|||||||
data_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
|
data_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
|
||||||
data_buffer[1]= (uchar)ARCHIVE_VERSION;
|
data_buffer[1]= (uchar)ARCHIVE_VERSION;
|
||||||
|
|
||||||
if (gzwrite(file_to_write, &data_buffer, DATA_BUFFER_SIZE) !=
|
if (azwrite(file_to_write, &data_buffer, DATA_BUFFER_SIZE) !=
|
||||||
DATA_BUFFER_SIZE)
|
DATA_BUFFER_SIZE)
|
||||||
goto error;
|
goto error;
|
||||||
DBUG_PRINT("ha_archive::write_data_header", ("Check %u", (uint)data_buffer[0]));
|
DBUG_PRINT("ha_archive::write_data_header", ("Check %u", (uint)data_buffer[0]));
|
||||||
@ -427,8 +427,11 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
|
|||||||
a gzip file that can be both read and written we keep a writer open
|
a gzip file that can be both read and written we keep a writer open
|
||||||
that is shared amoung all open tables.
|
that is shared amoung all open tables.
|
||||||
*/
|
*/
|
||||||
if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
|
if (!(azopen(&(share->archive_write), share->data_file_name, O_WRONLY|O_APPEND|O_BINARY)))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Could not open archive write file"));
|
||||||
share->crashed= TRUE;
|
share->crashed= TRUE;
|
||||||
|
}
|
||||||
VOID(my_hash_insert(&archive_open_tables, (byte*) share));
|
VOID(my_hash_insert(&archive_open_tables, (byte*) share));
|
||||||
thr_lock_init(&share->lock);
|
thr_lock_init(&share->lock);
|
||||||
}
|
}
|
||||||
@ -453,7 +456,7 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
|
|||||||
thr_lock_delete(&share->lock);
|
thr_lock_delete(&share->lock);
|
||||||
VOID(pthread_mutex_destroy(&share->mutex));
|
VOID(pthread_mutex_destroy(&share->mutex));
|
||||||
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
|
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
|
||||||
if (gzclose(share->archive_write) == Z_ERRNO)
|
if (azclose(&(share->archive_write)))
|
||||||
rc= 1;
|
rc= 1;
|
||||||
if (my_close(share->meta_file, MYF(0)))
|
if (my_close(share->meta_file, MYF(0)))
|
||||||
rc= 1;
|
rc= 1;
|
||||||
@ -494,7 +497,7 @@ int ha_archive::open(const char *name, int mode, uint test_if_locked)
|
|||||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM); // Not handled well by calling code!
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM); // Not handled well by calling code!
|
||||||
thr_lock_data_init(&share->lock,&lock,NULL);
|
thr_lock_data_init(&share->lock,&lock,NULL);
|
||||||
|
|
||||||
if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
|
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
|
||||||
{
|
{
|
||||||
if (errno == EROFS || errno == EACCES)
|
if (errno == EROFS || errno == EACCES)
|
||||||
DBUG_RETURN(my_errno= errno);
|
DBUG_RETURN(my_errno= errno);
|
||||||
@ -528,7 +531,7 @@ int ha_archive::close(void)
|
|||||||
DBUG_ENTER("ha_archive::close");
|
DBUG_ENTER("ha_archive::close");
|
||||||
|
|
||||||
/* First close stream */
|
/* First close stream */
|
||||||
if (gzclose(archive) == Z_ERRNO)
|
if (azclose(&archive))
|
||||||
rc= 1;
|
rc= 1;
|
||||||
/* then also close share */
|
/* then also close share */
|
||||||
rc|= free_share(share);
|
rc|= free_share(share);
|
||||||
@ -574,18 +577,18 @@ int ha_archive::create(const char *name, TABLE *table_arg,
|
|||||||
error= my_errno;
|
error= my_errno;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if ((archive= gzdopen(create_file, "wb")) == NULL)
|
if (!azdopen(&archive, create_file, O_WRONLY|O_BINARY))
|
||||||
{
|
{
|
||||||
error= errno;
|
error= errno;
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
if (write_data_header(archive))
|
if (write_data_header(&archive))
|
||||||
{
|
{
|
||||||
error= errno;
|
error= errno;
|
||||||
goto error3;
|
goto error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gzclose(archive))
|
if (azclose(&archive))
|
||||||
{
|
{
|
||||||
error= errno;
|
error= errno;
|
||||||
goto error2;
|
goto error2;
|
||||||
@ -596,8 +599,8 @@ int ha_archive::create(const char *name, TABLE *table_arg,
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
error3:
|
error3:
|
||||||
/* We already have an error, so ignore results of gzclose. */
|
/* We already have an error, so ignore results of azclose. */
|
||||||
(void)gzclose(archive);
|
(void)azclose(&archive);
|
||||||
error2:
|
error2:
|
||||||
my_close(create_file, MYF(0));
|
my_close(create_file, MYF(0));
|
||||||
delete_table(name);
|
delete_table(name);
|
||||||
@ -609,13 +612,13 @@ error:
|
|||||||
/*
|
/*
|
||||||
This is where the actual row is written out.
|
This is where the actual row is written out.
|
||||||
*/
|
*/
|
||||||
int ha_archive::real_write_row(byte *buf, gzFile writer)
|
int ha_archive::real_write_row(byte *buf, azio_stream *writer)
|
||||||
{
|
{
|
||||||
z_off_t written;
|
z_off_t written;
|
||||||
uint *ptr, *end;
|
uint *ptr, *end;
|
||||||
DBUG_ENTER("ha_archive::real_write_row");
|
DBUG_ENTER("ha_archive::real_write_row");
|
||||||
|
|
||||||
written= gzwrite(writer, buf, table->s->reclength);
|
written= azwrite(writer, buf, table->s->reclength);
|
||||||
DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
|
DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
|
||||||
if (!delayed_insert || !bulk_insert)
|
if (!delayed_insert || !bulk_insert)
|
||||||
share->dirty= TRUE;
|
share->dirty= TRUE;
|
||||||
@ -636,7 +639,7 @@ int ha_archive::real_write_row(byte *buf, gzFile writer)
|
|||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr);
|
((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr);
|
||||||
written= gzwrite(writer, data_ptr, (unsigned)size);
|
written= azwrite(writer, data_ptr, (unsigned)size);
|
||||||
if (written != (z_off_t)size)
|
if (written != (z_off_t)size)
|
||||||
DBUG_RETURN(errno ? errno : -1);
|
DBUG_RETURN(errno ? errno : -1);
|
||||||
}
|
}
|
||||||
@ -667,7 +670,7 @@ int ha_archive::write_row(byte *buf)
|
|||||||
table->timestamp_field->set_time();
|
table->timestamp_field->set_time();
|
||||||
pthread_mutex_lock(&share->mutex);
|
pthread_mutex_lock(&share->mutex);
|
||||||
share->rows_recorded++;
|
share->rows_recorded++;
|
||||||
rc= real_write_row(buf, share->archive_write);
|
rc= real_write_row(buf, &(share->archive_write));
|
||||||
pthread_mutex_unlock(&share->mutex);
|
pthread_mutex_unlock(&share->mutex);
|
||||||
|
|
||||||
DBUG_RETURN(rc);
|
DBUG_RETURN(rc);
|
||||||
@ -694,20 +697,20 @@ int ha_archive::rnd_init(bool scan)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
If dirty, we lock, and then reset/flush the data.
|
If dirty, we lock, and then reset/flush the data.
|
||||||
I found that just calling gzflush() doesn't always work.
|
I found that just calling azflush() doesn't always work.
|
||||||
*/
|
*/
|
||||||
if (share->dirty == TRUE)
|
if (share->dirty == TRUE)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&share->mutex);
|
pthread_mutex_lock(&share->mutex);
|
||||||
if (share->dirty == TRUE)
|
if (share->dirty == TRUE)
|
||||||
{
|
{
|
||||||
gzflush(share->archive_write, Z_SYNC_FLUSH);
|
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
||||||
share->dirty= FALSE;
|
share->dirty= FALSE;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&share->mutex);
|
pthread_mutex_unlock(&share->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_data_header(archive))
|
if (read_data_header(&archive))
|
||||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,15 +722,15 @@ int ha_archive::rnd_init(bool scan)
|
|||||||
This is the method that is used to read a row. It assumes that the row is
|
This is the method that is used to read a row. It assumes that the row is
|
||||||
positioned where you want it.
|
positioned where you want it.
|
||||||
*/
|
*/
|
||||||
int ha_archive::get_row(gzFile file_to_read, byte *buf)
|
int ha_archive::get_row(azio_stream *file_to_read, byte *buf)
|
||||||
{
|
{
|
||||||
int read; // Bytes read, gzread() returns int
|
int read; // Bytes read, azread() returns int
|
||||||
uint *ptr, *end;
|
uint *ptr, *end;
|
||||||
char *last;
|
char *last;
|
||||||
size_t total_blob_length= 0;
|
size_t total_blob_length= 0;
|
||||||
DBUG_ENTER("ha_archive::get_row");
|
DBUG_ENTER("ha_archive::get_row");
|
||||||
|
|
||||||
read= gzread(file_to_read, buf, table->s->reclength);
|
read= azread(file_to_read, buf, table->s->reclength);
|
||||||
DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
|
DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
|
||||||
|
|
||||||
if (read == Z_STREAM_ERROR)
|
if (read == Z_STREAM_ERROR)
|
||||||
@ -762,7 +765,7 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf)
|
|||||||
size_t size= ((Field_blob*) table->field[*ptr])->get_length();
|
size_t size= ((Field_blob*) table->field[*ptr])->get_length();
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
read= gzread(file_to_read, last, size);
|
read= azread(file_to_read, last, size);
|
||||||
if ((size_t) read != size)
|
if ((size_t) read != size)
|
||||||
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
||||||
((Field_blob*) table->field[*ptr])->set_ptr(size, last);
|
((Field_blob*) table->field[*ptr])->set_ptr(size, last);
|
||||||
@ -792,8 +795,8 @@ int ha_archive::rnd_next(byte *buf)
|
|||||||
|
|
||||||
statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
|
statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
|
||||||
&LOCK_status);
|
&LOCK_status);
|
||||||
current_position= gztell(archive);
|
current_position= aztell(&archive);
|
||||||
rc= get_row(archive, buf);
|
rc= get_row(&archive, buf);
|
||||||
|
|
||||||
|
|
||||||
if (rc != HA_ERR_END_OF_FILE)
|
if (rc != HA_ERR_END_OF_FILE)
|
||||||
@ -830,9 +833,9 @@ int ha_archive::rnd_pos(byte * buf, byte *pos)
|
|||||||
statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
|
statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
|
||||||
&LOCK_status);
|
&LOCK_status);
|
||||||
current_position= (z_off_t)my_get_ptr(pos, ref_length);
|
current_position= (z_off_t)my_get_ptr(pos, ref_length);
|
||||||
(void)gzseek(archive, current_position, SEEK_SET);
|
(void)azseek(&archive, current_position, SEEK_SET);
|
||||||
|
|
||||||
DBUG_RETURN(get_row(archive, buf));
|
DBUG_RETURN(get_row(&archive, buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -861,17 +864,17 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("ha_archive::optimize");
|
DBUG_ENTER("ha_archive::optimize");
|
||||||
int rc;
|
int rc;
|
||||||
gzFile writer;
|
azio_stream writer;
|
||||||
char writer_filename[FN_REFLEN];
|
char writer_filename[FN_REFLEN];
|
||||||
|
|
||||||
/* Flush any waiting data */
|
/* Flush any waiting data */
|
||||||
gzflush(share->archive_write, Z_SYNC_FLUSH);
|
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
||||||
|
|
||||||
/* Lets create a file to contain the new data */
|
/* Lets create a file to contain the new data */
|
||||||
fn_format(writer_filename, share->table_name, "", ARN,
|
fn_format(writer_filename, share->table_name, "", ARN,
|
||||||
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
|
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
|
||||||
|
|
||||||
if ((writer= gzopen(writer_filename, "wb")) == NULL)
|
if (!(azopen(&writer, writer_filename, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)))
|
||||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -881,6 +884,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
|
|
||||||
if (check_opt->flags == T_EXTEND)
|
if (check_opt->flags == T_EXTEND)
|
||||||
{
|
{
|
||||||
|
DBUG_PRINT("info", ("archive extended rebuild"));
|
||||||
byte *buf;
|
byte *buf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -897,14 +901,14 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
Now we will rewind the archive file so that we are positioned at the
|
Now we will rewind the archive file so that we are positioned at the
|
||||||
start of the file.
|
start of the file.
|
||||||
*/
|
*/
|
||||||
rc= read_data_header(archive);
|
rc= read_data_header(&archive);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Assuming now error from rewinding the archive file, we now write out the
|
Assuming now error from rewinding the archive file, we now write out the
|
||||||
new header for out data file.
|
new header for out data file.
|
||||||
*/
|
*/
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc= write_data_header(writer);
|
rc= write_data_header(&writer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
On success of writing out the new header, we now fetch each row and
|
On success of writing out the new header, we now fetch each row and
|
||||||
@ -913,9 +917,9 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
share->rows_recorded= 0;
|
share->rows_recorded= 0;
|
||||||
while (!(rc= get_row(archive, buf)))
|
while (!(rc= get_row(&archive, buf)))
|
||||||
{
|
{
|
||||||
real_write_row(buf, writer);
|
real_write_row(buf, &writer);
|
||||||
share->rows_recorded++;
|
share->rows_recorded++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -926,31 +930,31 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DBUG_PRINT("info", ("archive quick rebuild"));
|
||||||
/*
|
/*
|
||||||
The quick method is to just read the data raw, and then compress it directly.
|
The quick method is to just read the data raw, and then compress it directly.
|
||||||
*/
|
*/
|
||||||
int read; // Bytes read, gzread() returns int
|
int read; // Bytes read, azread() returns int
|
||||||
char block[IO_SIZE];
|
char block[IO_SIZE];
|
||||||
if (gzrewind(archive) == -1)
|
if (azrewind(&archive) == -1)
|
||||||
{
|
{
|
||||||
rc= HA_ERR_CRASHED_ON_USAGE;
|
rc= HA_ERR_CRASHED_ON_USAGE;
|
||||||
|
DBUG_PRINT("info", ("archive HA_ERR_CRASHED_ON_USAGE"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((read= gzread(archive, block, IO_SIZE)))
|
while ((read= azread(&archive, block, IO_SIZE)))
|
||||||
gzwrite(writer, block, read);
|
azwrite(&writer, block, read);
|
||||||
}
|
}
|
||||||
|
|
||||||
gzflush(writer, Z_SYNC_FLUSH);
|
azclose(&writer);
|
||||||
gzclose(share->archive_write);
|
|
||||||
share->archive_write= writer;
|
|
||||||
|
|
||||||
my_rename(writer_filename,share->data_file_name,MYF(0));
|
my_rename(writer_filename,share->data_file_name,MYF(0));
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
gzclose(writer);
|
azclose(&writer);
|
||||||
|
|
||||||
DBUG_RETURN(rc);
|
DBUG_RETURN(rc);
|
||||||
}
|
}
|
||||||
@ -1092,7 +1096,7 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
|
|
||||||
thd->proc_info= "Checking table";
|
thd->proc_info= "Checking table";
|
||||||
/* Flush any waiting data */
|
/* Flush any waiting data */
|
||||||
gzflush(share->archive_write, Z_SYNC_FLUSH);
|
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First we create a buffer that we can use for reading rows, and can pass
|
First we create a buffer that we can use for reading rows, and can pass
|
||||||
@ -1106,10 +1110,10 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
start of the file.
|
start of the file.
|
||||||
*/
|
*/
|
||||||
if (!rc)
|
if (!rc)
|
||||||
read_data_header(archive);
|
read_data_header(&archive);
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
while (!(rc= get_row(archive, buf)))
|
while (!(rc= get_row(&archive, buf)))
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
my_free((char*)buf, MYF(0));
|
my_free((char*)buf, MYF(0));
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include "../storage/archive/azlib.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Please read ha_archive.cc first. If you are looking for more general
|
Please read ha_archive.cc first. If you are looking for more general
|
||||||
@ -33,7 +34,7 @@ typedef struct st_archive_share {
|
|||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
THR_LOCK lock;
|
THR_LOCK lock;
|
||||||
File meta_file; /* Meta file we use */
|
File meta_file; /* Meta file we use */
|
||||||
gzFile archive_write; /* Archive file we are working with */
|
azio_stream archive_write; /* Archive file we are working with */
|
||||||
bool dirty; /* Flag for if a flush should occur */
|
bool dirty; /* Flag for if a flush should occur */
|
||||||
bool crashed; /* Meta file is crashed */
|
bool crashed; /* Meta file is crashed */
|
||||||
ha_rows rows_recorded; /* Number of rows in tables */
|
ha_rows rows_recorded; /* Number of rows in tables */
|
||||||
@ -49,7 +50,7 @@ class ha_archive: public handler
|
|||||||
{
|
{
|
||||||
THR_LOCK_DATA lock; /* MySQL lock */
|
THR_LOCK_DATA lock; /* MySQL lock */
|
||||||
ARCHIVE_SHARE *share; /* Shared lock info */
|
ARCHIVE_SHARE *share; /* Shared lock info */
|
||||||
gzFile archive; /* Archive file we are working with */
|
azio_stream archive; /* Archive file we are working with */
|
||||||
z_off_t current_position; /* The position of the row we just read */
|
z_off_t current_position; /* The position of the row we just read */
|
||||||
byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
|
byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
|
||||||
String buffer; /* Buffer used for blob storage */
|
String buffer; /* Buffer used for blob storage */
|
||||||
@ -77,19 +78,19 @@ public:
|
|||||||
int open(const char *name, int mode, uint test_if_locked);
|
int open(const char *name, int mode, uint test_if_locked);
|
||||||
int close(void);
|
int close(void);
|
||||||
int write_row(byte * buf);
|
int write_row(byte * buf);
|
||||||
int real_write_row(byte *buf, gzFile writer);
|
int real_write_row(byte *buf, azio_stream *writer);
|
||||||
int delete_all_rows();
|
int delete_all_rows();
|
||||||
int rnd_init(bool scan=1);
|
int rnd_init(bool scan=1);
|
||||||
int rnd_next(byte *buf);
|
int rnd_next(byte *buf);
|
||||||
int rnd_pos(byte * buf, byte *pos);
|
int rnd_pos(byte * buf, byte *pos);
|
||||||
int get_row(gzFile file_to_read, byte *buf);
|
int get_row(azio_stream *file_to_read, byte *buf);
|
||||||
int read_meta_file(File meta_file, ha_rows *rows);
|
int read_meta_file(File meta_file, ha_rows *rows);
|
||||||
int write_meta_file(File meta_file, ha_rows rows, bool dirty);
|
int write_meta_file(File meta_file, ha_rows rows, bool dirty);
|
||||||
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
|
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
|
||||||
int free_share(ARCHIVE_SHARE *share);
|
int free_share(ARCHIVE_SHARE *share);
|
||||||
bool auto_repair() const { return 1; } // For the moment we just do this
|
bool auto_repair() const { return 1; } // For the moment we just do this
|
||||||
int read_data_header(gzFile file_to_read);
|
int read_data_header(azio_stream *file_to_read);
|
||||||
int write_data_header(gzFile file_to_write);
|
int write_data_header(azio_stream *file_to_write);
|
||||||
void position(const byte *record);
|
void position(const byte *record);
|
||||||
void info(uint);
|
void info(uint);
|
||||||
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
||||||
|
@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = foreign
|
|||||||
# These are built from source in the Docs directory
|
# These are built from source in the Docs directory
|
||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
SUBDIRS =
|
SUBDIRS =
|
||||||
DIST_SUBDIRS = . bdb heap innobase myisam myisammrg ndb
|
DIST_SUBDIRS = . bdb heap innobase myisam myisammrg ndb archive
|
||||||
|
|
||||||
# Don't update the files from bitkeeper
|
# Don't update the files from bitkeeper
|
||||||
%::SCCS/s.%
|
%::SCCS/s.%
|
||||||
|
31
storage/archive/Makefile.am
Normal file
31
storage/archive/Makefile.am
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
|
||||||
|
@ZLIB_INCLUDES@
|
||||||
|
|
||||||
|
LDADD = libarchive.a $(top_srcdir)/mysys/libmysys.a \
|
||||||
|
$(top_srcdir)/dbug/libdbug.a \
|
||||||
|
$(top_srcdir)/strings/libmystrings.a \
|
||||||
|
@ZLIB_LIBS@
|
||||||
|
pkglib_LIBRARIES = libarchive.a
|
||||||
|
noinst_PROGRAMS = archive_test
|
||||||
|
archive_test_LDFLAGS = @NOINST_LDFLAGS@
|
||||||
|
noinst_HEADERS = azlib.h
|
||||||
|
libarchive_a_SOURCES = azio.c
|
||||||
|
|
||||||
|
# Don't update the files from bitkeeper
|
||||||
|
%::SCCS/s.%
|
48
storage/archive/archive_test.c
Normal file
48
storage/archive/archive_test.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <azlib.h>
|
||||||
|
|
||||||
|
#define TEST_STRING "This is a test"
|
||||||
|
#define BUFFER_LEN 1024
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
azio_stream foo, foo1;
|
||||||
|
char buffer[BUFFER_LEN];
|
||||||
|
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
|
if (!(ret= azopen(&foo, "test", O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)))
|
||||||
|
{
|
||||||
|
printf("Could not create test file\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
azwrite(&foo, TEST_STRING, sizeof(TEST_STRING));
|
||||||
|
azflush(&foo, Z_FINISH);
|
||||||
|
|
||||||
|
if (!(ret= azopen(&foo1, "test", O_RDONLY|O_BINARY)))
|
||||||
|
{
|
||||||
|
printf("Could not open test file\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret= azread(&foo1, buffer, BUFFER_LEN);
|
||||||
|
printf("Read %d bytes\n", ret);
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
azrewind(&foo1);
|
||||||
|
azclose(&foo);
|
||||||
|
if (!(ret= azopen(&foo, "test", O_APPEND|O_WRONLY|O_BINARY)))
|
||||||
|
{
|
||||||
|
printf("Could not create test file\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
azwrite(&foo, TEST_STRING, sizeof(TEST_STRING));
|
||||||
|
azflush(&foo, Z_FINISH);
|
||||||
|
ret= azread(&foo1, buffer, BUFFER_LEN);
|
||||||
|
printf("Read %d bytes\n", ret);
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
azclose(&foo);
|
||||||
|
azclose(&foo1);
|
||||||
|
|
||||||
|
//unlink("test");
|
||||||
|
return 0;
|
||||||
|
}
|
653
storage/archive/azio.c
Normal file
653
storage/archive/azio.c
Normal file
@ -0,0 +1,653 @@
|
|||||||
|
/*
|
||||||
|
azio is a modified version of gzio. It makes use of mysys and removes mallocs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* gzio.c -- IO on .gz files
|
||||||
|
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*
|
||||||
|
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
#include "azlib.h"
|
||||||
|
|
||||||
|
static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
|
||||||
|
|
||||||
|
/* gzip flag byte */
|
||||||
|
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||||
|
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
|
||||||
|
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||||
|
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||||
|
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||||
|
#define RESERVED 0xE0 /* bits 5..7: reserved */
|
||||||
|
|
||||||
|
local int az_open(azio_stream *s, const char *path, int Flags, File fd);
|
||||||
|
local int do_flush(azio_stream *file, int flush);
|
||||||
|
local int get_byte(azio_stream *s);
|
||||||
|
local void check_header(azio_stream *s);
|
||||||
|
local int destroy(azio_stream *s);
|
||||||
|
local void putLong(File file, uLong x);
|
||||||
|
local uLong getLong(azio_stream *s);
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||||
|
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
|
||||||
|
or path name (if fd == -1).
|
||||||
|
az_open returns NULL if the file could not be opened or if there was
|
||||||
|
insufficient memory to allocate the (de)compression state; errno
|
||||||
|
can be checked to distinguish the two cases (if errno is zero, the
|
||||||
|
zlib error is Z_MEM_ERROR).
|
||||||
|
*/
|
||||||
|
local int az_open (azio_stream *s, const char *path, int Flags, File fd)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
int level = Z_DEFAULT_COMPRESSION; /* compression level */
|
||||||
|
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
|
||||||
|
|
||||||
|
s->stream.zalloc = (alloc_func)0;
|
||||||
|
s->stream.zfree = (free_func)0;
|
||||||
|
s->stream.opaque = (voidpf)0;
|
||||||
|
zmemzero(s->inbuf, Z_BUFSIZE);
|
||||||
|
zmemzero(s->outbuf, Z_BUFSIZE);
|
||||||
|
s->stream.next_in = s->inbuf;
|
||||||
|
s->stream.next_out = s->outbuf;
|
||||||
|
s->stream.avail_in = s->stream.avail_out = 0;
|
||||||
|
s->z_err = Z_OK;
|
||||||
|
s->z_eof = 0;
|
||||||
|
s->in = 0;
|
||||||
|
s->out = 0;
|
||||||
|
s->back = EOF;
|
||||||
|
s->crc = crc32(0L, Z_NULL, 0);
|
||||||
|
s->transparent = 0;
|
||||||
|
s->mode = 'r';
|
||||||
|
|
||||||
|
if (Flags & O_WRONLY || Flags & O_APPEND)
|
||||||
|
s->mode = 'w';
|
||||||
|
|
||||||
|
if (s->mode == 'w') {
|
||||||
|
#ifdef NO_GZCOMPRESS
|
||||||
|
err = Z_STREAM_ERROR;
|
||||||
|
#else
|
||||||
|
err = deflateInit2(&(s->stream), level,
|
||||||
|
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
|
||||||
|
/* windowBits is passed < 0 to suppress zlib header */
|
||||||
|
|
||||||
|
s->stream.next_out = s->outbuf;
|
||||||
|
#endif
|
||||||
|
if (err != Z_OK)
|
||||||
|
{
|
||||||
|
destroy(s);
|
||||||
|
return Z_NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s->stream.next_in = s->inbuf;
|
||||||
|
|
||||||
|
err = inflateInit2(&(s->stream), -MAX_WBITS);
|
||||||
|
/* windowBits is passed < 0 to tell that there is no zlib header.
|
||||||
|
* Note that in this case inflate *requires* an extra "dummy" byte
|
||||||
|
* after the compressed stream in order to complete decompression and
|
||||||
|
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
|
||||||
|
* present after the compressed stream.
|
||||||
|
*/
|
||||||
|
if (err != Z_OK)
|
||||||
|
{
|
||||||
|
destroy(s);
|
||||||
|
return Z_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->stream.avail_out = Z_BUFSIZE;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
|
||||||
|
|
||||||
|
if (s->file < 0 )
|
||||||
|
{
|
||||||
|
destroy(s);
|
||||||
|
return Z_NULL;
|
||||||
|
}
|
||||||
|
if (s->mode == 'w') {
|
||||||
|
char buffer[10];
|
||||||
|
/* Write a very simple .gz header:
|
||||||
|
*/
|
||||||
|
snprintf(buffer, 10, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
|
||||||
|
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
|
||||||
|
s->start = 10L;
|
||||||
|
my_write(s->file, buffer, s->start, MYF(0));
|
||||||
|
/* We use 10L instead of ftell(s->file) to because ftell causes an
|
||||||
|
* fflush on some systems. This version of the library doesn't use
|
||||||
|
* start anyway in write mode, so this initialization is not
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
check_header(s); /* skip the .gz header */
|
||||||
|
s->start = my_tell(s->file, MYF(0)) - s->stream.avail_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Opens a gzip (.gz) file for reading or writing.
|
||||||
|
*/
|
||||||
|
int azopen(azio_stream *s, const char *path, int Flags)
|
||||||
|
{
|
||||||
|
return az_open(s, path, Flags, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
|
||||||
|
to mimic the behavio(u)r of fdopen.
|
||||||
|
*/
|
||||||
|
int azdopen(azio_stream *s, File fd, int Flags)
|
||||||
|
{
|
||||||
|
if (fd < 0) return 0;
|
||||||
|
|
||||||
|
return az_open (s, NULL, Flags, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Read a byte from a azio_stream; update next_in and avail_in. Return EOF
|
||||||
|
for end of file.
|
||||||
|
IN assertion: the stream s has been sucessfully opened for reading.
|
||||||
|
*/
|
||||||
|
local int get_byte(s)
|
||||||
|
azio_stream *s;
|
||||||
|
{
|
||||||
|
if (s->z_eof) return EOF;
|
||||||
|
if (s->stream.avail_in == 0)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
s->stream.avail_in = my_read(s->file, (byte *)s->inbuf, Z_BUFSIZE, MYF(0));
|
||||||
|
if (s->stream.avail_in == 0)
|
||||||
|
{
|
||||||
|
s->z_eof = 1;
|
||||||
|
// if (ferror(s->file)) s->z_err = Z_ERRNO;
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
s->stream.next_in = s->inbuf;
|
||||||
|
}
|
||||||
|
s->stream.avail_in--;
|
||||||
|
return *(s->stream.next_in)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Check the gzip header of a azio_stream opened for reading. Set the stream
|
||||||
|
mode to transparent if the gzip magic header is not present; set s->err
|
||||||
|
to Z_DATA_ERROR if the magic header is present but the rest of the header
|
||||||
|
is incorrect.
|
||||||
|
IN assertion: the stream s has already been created sucessfully;
|
||||||
|
s->stream.avail_in is zero for the first time, but may be non-zero
|
||||||
|
for concatenated .gz files.
|
||||||
|
*/
|
||||||
|
local void check_header(azio_stream *s)
|
||||||
|
{
|
||||||
|
int method; /* method byte */
|
||||||
|
int flags; /* flags byte */
|
||||||
|
uInt len;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
/* Assure two bytes in the buffer so we can peek ahead -- handle case
|
||||||
|
where first byte of header is at the end of the buffer after the last
|
||||||
|
gzip segment */
|
||||||
|
len = s->stream.avail_in;
|
||||||
|
if (len < 2) {
|
||||||
|
if (len) s->inbuf[0] = s->stream.next_in[0];
|
||||||
|
errno = 0;
|
||||||
|
len = (uInt)my_read(s->file, (byte *)s->inbuf + len, Z_BUFSIZE >> len, MYF(0));
|
||||||
|
if (len == 0) s->z_err = Z_ERRNO;
|
||||||
|
s->stream.avail_in += len;
|
||||||
|
s->stream.next_in = s->inbuf;
|
||||||
|
if (s->stream.avail_in < 2) {
|
||||||
|
s->transparent = s->stream.avail_in;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Peek ahead to check the gzip magic header */
|
||||||
|
if (s->stream.next_in[0] != gz_magic[0] ||
|
||||||
|
s->stream.next_in[1] != gz_magic[1]) {
|
||||||
|
s->transparent = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->stream.avail_in -= 2;
|
||||||
|
s->stream.next_in += 2;
|
||||||
|
|
||||||
|
/* Check the rest of the gzip header */
|
||||||
|
method = get_byte(s);
|
||||||
|
flags = get_byte(s);
|
||||||
|
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
|
||||||
|
s->z_err = Z_DATA_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Discard time, xflags and OS code: */
|
||||||
|
for (len = 0; len < 6; len++) (void)get_byte(s);
|
||||||
|
|
||||||
|
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
|
||||||
|
len = (uInt)get_byte(s);
|
||||||
|
len += ((uInt)get_byte(s))<<8;
|
||||||
|
/* len is garbage if EOF but the loop below will quit anyway */
|
||||||
|
while (len-- != 0 && get_byte(s) != EOF) ;
|
||||||
|
}
|
||||||
|
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
|
||||||
|
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||||
|
}
|
||||||
|
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
|
||||||
|
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||||
|
}
|
||||||
|
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
|
||||||
|
for (len = 0; len < 2; len++) (void)get_byte(s);
|
||||||
|
}
|
||||||
|
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
* Cleanup then free the given azio_stream. Return a zlib error code.
|
||||||
|
Try freeing in the reverse order of allocations.
|
||||||
|
*/
|
||||||
|
local int destroy (s)
|
||||||
|
azio_stream *s;
|
||||||
|
{
|
||||||
|
int err = Z_OK;
|
||||||
|
|
||||||
|
if (s->stream.state != NULL) {
|
||||||
|
if (s->mode == 'w') {
|
||||||
|
#ifdef NO_GZCOMPRESS
|
||||||
|
err = Z_STREAM_ERROR;
|
||||||
|
#else
|
||||||
|
err = deflateEnd(&(s->stream));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (s->mode == 'r')
|
||||||
|
{
|
||||||
|
err = inflateEnd(&(s->stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->file < 0 && my_close(s->file, MYF(0)))
|
||||||
|
{
|
||||||
|
#ifdef ESPIPE
|
||||||
|
if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
|
||||||
|
#endif
|
||||||
|
err = Z_ERRNO;
|
||||||
|
}
|
||||||
|
if (s->z_err < 0) err = s->z_err;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Reads the given number of uncompressed bytes from the compressed file.
|
||||||
|
azread returns the number of bytes actually read (0 for end of file).
|
||||||
|
*/
|
||||||
|
int ZEXPORT azread ( azio_stream *s, voidp buf, unsigned len)
|
||||||
|
{
|
||||||
|
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
|
||||||
|
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
|
||||||
|
|
||||||
|
if (s->mode != 'r') return Z_STREAM_ERROR;
|
||||||
|
|
||||||
|
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
|
||||||
|
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
|
||||||
|
|
||||||
|
next_out = (Byte*)buf;
|
||||||
|
s->stream.next_out = (Bytef*)buf;
|
||||||
|
s->stream.avail_out = len;
|
||||||
|
|
||||||
|
if (s->stream.avail_out && s->back != EOF) {
|
||||||
|
*next_out++ = s->back;
|
||||||
|
s->stream.next_out++;
|
||||||
|
s->stream.avail_out--;
|
||||||
|
s->back = EOF;
|
||||||
|
s->out++;
|
||||||
|
start++;
|
||||||
|
if (s->last) {
|
||||||
|
s->z_err = Z_STREAM_END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (s->stream.avail_out != 0) {
|
||||||
|
|
||||||
|
if (s->transparent) {
|
||||||
|
/* Copy first the lookahead bytes: */
|
||||||
|
uInt n = s->stream.avail_in;
|
||||||
|
if (n > s->stream.avail_out) n = s->stream.avail_out;
|
||||||
|
if (n > 0) {
|
||||||
|
zmemcpy(s->stream.next_out, s->stream.next_in, n);
|
||||||
|
next_out += n;
|
||||||
|
s->stream.next_out = (Bytef *)next_out;
|
||||||
|
s->stream.next_in += n;
|
||||||
|
s->stream.avail_out -= n;
|
||||||
|
s->stream.avail_in -= n;
|
||||||
|
}
|
||||||
|
if (s->stream.avail_out > 0)
|
||||||
|
{
|
||||||
|
s->stream.avail_out -=
|
||||||
|
(uInt)my_read(s->file, (byte *)next_out, s->stream.avail_out, MYF(0));
|
||||||
|
}
|
||||||
|
len -= s->stream.avail_out;
|
||||||
|
s->in += len;
|
||||||
|
s->out += len;
|
||||||
|
if (len == 0) s->z_eof = 1;
|
||||||
|
return (int)len;
|
||||||
|
}
|
||||||
|
if (s->stream.avail_in == 0 && !s->z_eof) {
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
s->stream.avail_in = (uInt)my_read(s->file, (byte *)s->inbuf, Z_BUFSIZE, MYF(0));
|
||||||
|
if (s->stream.avail_in == 0)
|
||||||
|
{
|
||||||
|
s->z_eof = 1;
|
||||||
|
}
|
||||||
|
s->stream.next_in = (Bytef *)s->inbuf;
|
||||||
|
}
|
||||||
|
s->in += s->stream.avail_in;
|
||||||
|
s->out += s->stream.avail_out;
|
||||||
|
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
|
||||||
|
s->in -= s->stream.avail_in;
|
||||||
|
s->out -= s->stream.avail_out;
|
||||||
|
|
||||||
|
if (s->z_err == Z_STREAM_END) {
|
||||||
|
/* Check CRC and original size */
|
||||||
|
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||||
|
start = s->stream.next_out;
|
||||||
|
|
||||||
|
if (getLong(s) != s->crc) {
|
||||||
|
s->z_err = Z_DATA_ERROR;
|
||||||
|
} else {
|
||||||
|
(void)getLong(s);
|
||||||
|
/* The uncompressed length returned by above getlong() may be
|
||||||
|
* different from s->out in case of concatenated .gz files.
|
||||||
|
* Check for such files:
|
||||||
|
*/
|
||||||
|
check_header(s);
|
||||||
|
if (s->z_err == Z_OK) {
|
||||||
|
inflateReset(&(s->stream));
|
||||||
|
s->crc = crc32(0L, Z_NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->z_err != Z_OK || s->z_eof) break;
|
||||||
|
}
|
||||||
|
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||||
|
|
||||||
|
if (len == s->stream.avail_out &&
|
||||||
|
(s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
|
||||||
|
return -1;
|
||||||
|
return (int)(len - s->stream.avail_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NO_GZCOMPRESS
|
||||||
|
/* ===========================================================================
|
||||||
|
Writes the given number of uncompressed bytes into the compressed file.
|
||||||
|
azwrite returns the number of bytes actually written (0 in case of error).
|
||||||
|
*/
|
||||||
|
int azwrite (azio_stream *s, voidpc buf, unsigned len)
|
||||||
|
{
|
||||||
|
|
||||||
|
s->stream.next_in = (Bytef*)buf;
|
||||||
|
s->stream.avail_in = len;
|
||||||
|
|
||||||
|
while (s->stream.avail_in != 0)
|
||||||
|
{
|
||||||
|
if (s->stream.avail_out == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
s->stream.next_out = s->outbuf;
|
||||||
|
if (my_write(s->file, (byte *)s->outbuf, Z_BUFSIZE, MYF(0)) != Z_BUFSIZE)
|
||||||
|
{
|
||||||
|
s->z_err = Z_ERRNO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->stream.avail_out = Z_BUFSIZE;
|
||||||
|
}
|
||||||
|
s->in += s->stream.avail_in;
|
||||||
|
s->out += s->stream.avail_out;
|
||||||
|
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
|
||||||
|
s->in -= s->stream.avail_in;
|
||||||
|
s->out -= s->stream.avail_out;
|
||||||
|
if (s->z_err != Z_OK) break;
|
||||||
|
}
|
||||||
|
s->crc = crc32(s->crc, (const Bytef *)buf, len);
|
||||||
|
|
||||||
|
return (int)(len - s->stream.avail_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Flushes all pending output into the compressed file. The parameter
|
||||||
|
flush is as in the deflate() function.
|
||||||
|
*/
|
||||||
|
local int do_flush (s, flush)
|
||||||
|
azio_stream *s;
|
||||||
|
int flush;
|
||||||
|
{
|
||||||
|
uInt len;
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
|
||||||
|
|
||||||
|
s->stream.avail_in = 0; /* should be zero already anyway */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
len = Z_BUFSIZE - s->stream.avail_out;
|
||||||
|
|
||||||
|
if (len != 0) {
|
||||||
|
if ((uInt)my_write(s->file, (byte *)s->outbuf, len, MYF(0)) != len)
|
||||||
|
{
|
||||||
|
s->z_err = Z_ERRNO;
|
||||||
|
return Z_ERRNO;
|
||||||
|
}
|
||||||
|
s->stream.next_out = s->outbuf;
|
||||||
|
s->stream.avail_out = Z_BUFSIZE;
|
||||||
|
}
|
||||||
|
if (done) break;
|
||||||
|
s->out += s->stream.avail_out;
|
||||||
|
s->z_err = deflate(&(s->stream), flush);
|
||||||
|
s->out -= s->stream.avail_out;
|
||||||
|
|
||||||
|
/* Ignore the second of two consecutive flushes: */
|
||||||
|
if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
|
||||||
|
|
||||||
|
/* deflate has finished flushing only when it hasn't used up
|
||||||
|
* all the available space in the output buffer:
|
||||||
|
*/
|
||||||
|
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
|
||||||
|
|
||||||
|
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
|
||||||
|
}
|
||||||
|
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZEXPORT azflush (s, flush)
|
||||||
|
azio_stream *s;
|
||||||
|
int flush;
|
||||||
|
{
|
||||||
|
int err = do_flush (s, flush);
|
||||||
|
|
||||||
|
if (err) return err;
|
||||||
|
my_sync(s->file, MYF(0));
|
||||||
|
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Rewinds input file.
|
||||||
|
*/
|
||||||
|
int azrewind (s)
|
||||||
|
azio_stream *s;
|
||||||
|
{
|
||||||
|
if (s == NULL || s->mode != 'r') return -1;
|
||||||
|
|
||||||
|
s->z_err = Z_OK;
|
||||||
|
s->z_eof = 0;
|
||||||
|
s->back = EOF;
|
||||||
|
s->stream.avail_in = 0;
|
||||||
|
s->stream.next_in = (Bytef *)s->inbuf;
|
||||||
|
s->crc = crc32(0L, Z_NULL, 0);
|
||||||
|
if (!s->transparent) (void)inflateReset(&s->stream);
|
||||||
|
s->in = 0;
|
||||||
|
s->out = 0;
|
||||||
|
return my_seek(s->file, s->start, MY_SEEK_SET, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Sets the starting position for the next azread or azwrite on the given
|
||||||
|
compressed file. The offset represents a number of bytes in the
|
||||||
|
azseek returns the resulting offset location as measured in bytes from
|
||||||
|
the beginning of the uncompressed stream, or -1 in case of error.
|
||||||
|
SEEK_END is not implemented, returns error.
|
||||||
|
In this version of the library, azseek can be extremely slow.
|
||||||
|
*/
|
||||||
|
z_off_t azseek (s, offset, whence)
|
||||||
|
azio_stream *s;
|
||||||
|
z_off_t offset;
|
||||||
|
int whence;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (s == NULL || whence == SEEK_END ||
|
||||||
|
s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->mode == 'w') {
|
||||||
|
#ifdef NO_GZCOMPRESS
|
||||||
|
return -1L;
|
||||||
|
#else
|
||||||
|
if (whence == SEEK_SET) {
|
||||||
|
offset -= s->in;
|
||||||
|
}
|
||||||
|
if (offset < 0) return -1L;
|
||||||
|
|
||||||
|
/* At this point, offset is the number of zero bytes to write. */
|
||||||
|
/* There was a zmemzero here if inbuf was null -Brian */
|
||||||
|
while (offset > 0) {
|
||||||
|
uInt size = Z_BUFSIZE;
|
||||||
|
if (offset < Z_BUFSIZE) size = (uInt)offset;
|
||||||
|
|
||||||
|
size = azwrite(s, s->inbuf, size);
|
||||||
|
if (size == 0) return -1L;
|
||||||
|
|
||||||
|
offset -= size;
|
||||||
|
}
|
||||||
|
return s->in;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* Rest of function is for reading only */
|
||||||
|
|
||||||
|
/* compute absolute position */
|
||||||
|
if (whence == SEEK_CUR) {
|
||||||
|
offset += s->out;
|
||||||
|
}
|
||||||
|
if (offset < 0) return -1L;
|
||||||
|
|
||||||
|
if (s->transparent) {
|
||||||
|
/* map to my_seek */
|
||||||
|
s->back = EOF;
|
||||||
|
s->stream.avail_in = 0;
|
||||||
|
s->stream.next_in = (Bytef *)s->inbuf;
|
||||||
|
if (my_seek(s->file, offset, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) return -1L;
|
||||||
|
|
||||||
|
s->in = s->out = offset;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For a negative seek, rewind and use positive seek */
|
||||||
|
if (offset >= s->out) {
|
||||||
|
offset -= s->out;
|
||||||
|
} else if (azrewind(s) < 0) {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
/* offset is now the number of bytes to skip. */
|
||||||
|
|
||||||
|
if (offset && s->back != EOF) {
|
||||||
|
s->back = EOF;
|
||||||
|
s->out++;
|
||||||
|
offset--;
|
||||||
|
if (s->last) s->z_err = Z_STREAM_END;
|
||||||
|
}
|
||||||
|
while (offset > 0) {
|
||||||
|
int size = Z_BUFSIZE;
|
||||||
|
if (offset < Z_BUFSIZE) size = (int)offset;
|
||||||
|
|
||||||
|
size = azread(s, s->outbuf, (uInt)size);
|
||||||
|
if (size <= 0) return -1L;
|
||||||
|
offset -= size;
|
||||||
|
}
|
||||||
|
return s->out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Returns the starting position for the next azread or azwrite on the
|
||||||
|
given compressed file. This position represents a number of bytes in the
|
||||||
|
uncompressed data stream.
|
||||||
|
*/
|
||||||
|
z_off_t ZEXPORT aztell (file)
|
||||||
|
azio_stream *file;
|
||||||
|
{
|
||||||
|
return azseek(file, 0L, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Outputs a long in LSB order to the given file
|
||||||
|
*/
|
||||||
|
local void putLong (File file, uLong x)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
byte buffer[1];
|
||||||
|
|
||||||
|
for (n = 0; n < 4; n++)
|
||||||
|
{
|
||||||
|
buffer[0]= (int)(x & 0xff);
|
||||||
|
my_write(file, buffer, 1, MYF(0));
|
||||||
|
x >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Reads a long in LSB order from the given azio_stream. Sets z_err in case
|
||||||
|
of error.
|
||||||
|
*/
|
||||||
|
local uLong getLong (azio_stream *s)
|
||||||
|
{
|
||||||
|
uLong x = (uLong)get_byte(s);
|
||||||
|
int c;
|
||||||
|
|
||||||
|
x += ((uLong)get_byte(s))<<8;
|
||||||
|
x += ((uLong)get_byte(s))<<16;
|
||||||
|
c = get_byte(s);
|
||||||
|
if (c == EOF) s->z_err = Z_DATA_ERROR;
|
||||||
|
x += ((uLong)c)<<24;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Flushes all pending output if necessary, closes the compressed file
|
||||||
|
and deallocates all the (de)compression state.
|
||||||
|
*/
|
||||||
|
int azclose (azio_stream *s)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (s == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
||||||
|
if (s->mode == 'w') {
|
||||||
|
#ifdef NO_GZCOMPRESS
|
||||||
|
return Z_STREAM_ERROR;
|
||||||
|
#else
|
||||||
|
if (do_flush (s, Z_FINISH) != Z_OK)
|
||||||
|
return destroy(s);
|
||||||
|
|
||||||
|
putLong(s->file, s->crc);
|
||||||
|
putLong(s->file, (uLong)(s->in & 0xffffffff));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return destroy(s);
|
||||||
|
}
|
278
storage/archive/azlib.h
Normal file
278
storage/archive/azlib.h
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
This libary has been modified for use by the MySQL Archive Engine.
|
||||||
|
*/
|
||||||
|
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||||
|
version 1.2.3, July 18th, 2005
|
||||||
|
|
||||||
|
Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
Jean-loup Gailly Mark Adler
|
||||||
|
jloup@gzip.org madler@alumni.caltech.edu
|
||||||
|
|
||||||
|
|
||||||
|
The data format used by the zlib library is described by RFCs (Request for
|
||||||
|
Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
|
||||||
|
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "../../mysys/mysys_priv.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
The 'zlib' compression library provides in-memory compression and
|
||||||
|
decompression functions, including integrity checks of the uncompressed
|
||||||
|
data. This version of the library supports only one compression method
|
||||||
|
(deflation) but other algorithms will be added later and will have the same
|
||||||
|
stream interface.
|
||||||
|
|
||||||
|
Compression can be done in a single step if the buffers are large
|
||||||
|
enough (for example if an input file is mmap'ed), or can be done by
|
||||||
|
repeated calls of the compression function. In the latter case, the
|
||||||
|
application must provide more input and/or consume the output
|
||||||
|
(providing more output space) before each call.
|
||||||
|
|
||||||
|
The compressed data format used by default by the in-memory functions is
|
||||||
|
the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
|
||||||
|
around a deflate stream, which is itself documented in RFC 1951.
|
||||||
|
|
||||||
|
The library also supports reading and writing files in gzip (.gz) format
|
||||||
|
with an interface similar to that of stdio using the functions that start
|
||||||
|
with "gz". The gzip format is different from the zlib format. gzip is a
|
||||||
|
gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
|
||||||
|
|
||||||
|
This library can optionally read and write gzip streams in memory as well.
|
||||||
|
|
||||||
|
The zlib format was designed to be compact and fast for use in memory
|
||||||
|
and on communications channels. The gzip format was designed for single-
|
||||||
|
file compression on file systems, has a larger header than zlib to maintain
|
||||||
|
directory information, and uses a different, slower check method than zlib.
|
||||||
|
|
||||||
|
The library does not install any signal handler. The decoder checks
|
||||||
|
the consistency of the compressed data, so the library should never
|
||||||
|
crash even in case of corrupted input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The application must update next_in and avail_in when avail_in has
|
||||||
|
dropped to zero. It must update next_out and avail_out when avail_out
|
||||||
|
has dropped to zero. The application must initialize zalloc, zfree and
|
||||||
|
opaque before calling the init function. All other fields are set by the
|
||||||
|
compression library and must not be updated by the application.
|
||||||
|
|
||||||
|
The opaque value provided by the application will be passed as the first
|
||||||
|
parameter for calls of zalloc and zfree. This can be useful for custom
|
||||||
|
memory management. The compression library attaches no meaning to the
|
||||||
|
opaque value.
|
||||||
|
|
||||||
|
zalloc must return Z_NULL if there is not enough memory for the object.
|
||||||
|
If zlib is used in a multi-threaded application, zalloc and zfree must be
|
||||||
|
thread safe.
|
||||||
|
|
||||||
|
On 16-bit systems, the functions zalloc and zfree must be able to allocate
|
||||||
|
exactly 65536 bytes, but will not be required to allocate more than this
|
||||||
|
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
|
||||||
|
pointers returned by zalloc for objects of exactly 65536 bytes *must*
|
||||||
|
have their offset normalized to zero. The default allocation function
|
||||||
|
provided by this library ensures this (see zutil.c). To reduce memory
|
||||||
|
requirements and avoid any allocation of 64K objects, at the expense of
|
||||||
|
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
|
||||||
|
|
||||||
|
The fields total_in and total_out can be used for statistics or
|
||||||
|
progress reports. After compression, total_in holds the total size of
|
||||||
|
the uncompressed data and may be saved for use in the decompressor
|
||||||
|
(particularly if the decompressor wants to decompress everything in
|
||||||
|
a single step).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
|
||||||
|
#define Z_NO_FLUSH 0
|
||||||
|
#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
|
||||||
|
#define Z_SYNC_FLUSH 2
|
||||||
|
#define Z_FULL_FLUSH 3
|
||||||
|
#define Z_FINISH 4
|
||||||
|
#define Z_BLOCK 5
|
||||||
|
/* Allowed flush values; see deflate() and inflate() below for details */
|
||||||
|
|
||||||
|
#define Z_OK 0
|
||||||
|
#define Z_STREAM_END 1
|
||||||
|
#define Z_NEED_DICT 2
|
||||||
|
#define Z_ERRNO (-1)
|
||||||
|
#define Z_STREAM_ERROR (-2)
|
||||||
|
#define Z_DATA_ERROR (-3)
|
||||||
|
#define Z_MEM_ERROR (-4)
|
||||||
|
#define Z_BUF_ERROR (-5)
|
||||||
|
#define Z_VERSION_ERROR (-6)
|
||||||
|
/* Return codes for the compression/decompression functions. Negative
|
||||||
|
* values are errors, positive values are used for special but normal events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Z_NO_COMPRESSION 0
|
||||||
|
#define Z_BEST_SPEED 1
|
||||||
|
#define Z_BEST_COMPRESSION 9
|
||||||
|
#define Z_DEFAULT_COMPRESSION (-1)
|
||||||
|
/* compression levels */
|
||||||
|
|
||||||
|
#define Z_FILTERED 1
|
||||||
|
#define Z_HUFFMAN_ONLY 2
|
||||||
|
#define Z_RLE 3
|
||||||
|
#define Z_FIXED 4
|
||||||
|
#define Z_DEFAULT_STRATEGY 0
|
||||||
|
/* compression strategy; see deflateInit2() below for details */
|
||||||
|
|
||||||
|
#define Z_BINARY 0
|
||||||
|
#define Z_TEXT 1
|
||||||
|
#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
|
||||||
|
#define Z_UNKNOWN 2
|
||||||
|
/* Possible values of the data_type field (though see inflate()) */
|
||||||
|
|
||||||
|
#define Z_DEFLATED 8
|
||||||
|
/* The deflate compression method (the only one supported in this version) */
|
||||||
|
|
||||||
|
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
|
||||||
|
#define Z_BUFSIZE 16384
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct azio_stream {
|
||||||
|
z_stream stream;
|
||||||
|
int z_err; /* error code for last stream operation */
|
||||||
|
int z_eof; /* set if end of input file */
|
||||||
|
File file; /* .gz file */
|
||||||
|
Byte inbuf[Z_BUFSIZE]; /* input buffer */
|
||||||
|
Byte outbuf[Z_BUFSIZE]; /* output buffer */
|
||||||
|
uLong crc; /* crc32 of uncompressed data */
|
||||||
|
char *msg; /* error message */
|
||||||
|
int transparent; /* 1 if input file is not a .gz file */
|
||||||
|
char mode; /* 'w' or 'r' */
|
||||||
|
z_off_t start; /* start of compressed data in file (header skipped) */
|
||||||
|
z_off_t in; /* bytes into deflate or inflate */
|
||||||
|
z_off_t out; /* bytes out of deflate or inflate */
|
||||||
|
int back; /* one character push-back */
|
||||||
|
int last; /* true if push-back is last character */
|
||||||
|
} azio_stream;
|
||||||
|
|
||||||
|
/* basic functions */
|
||||||
|
|
||||||
|
extern int azopen(azio_stream *s, const char *path, int Flags);
|
||||||
|
/*
|
||||||
|
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||||
|
is as in fopen ("rb" or "wb") but can also include a compression level
|
||||||
|
("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
|
||||||
|
Huffman only compression as in "wb1h", or 'R' for run-length encoding
|
||||||
|
as in "wb1R". (See the description of deflateInit2 for more information
|
||||||
|
about the strategy parameter.)
|
||||||
|
|
||||||
|
azopen can be used to read a file which is not in gzip format; in this
|
||||||
|
case gzread will directly read from the file without decompression.
|
||||||
|
|
||||||
|
azopen returns NULL if the file could not be opened or if there was
|
||||||
|
insufficient memory to allocate the (de)compression state; errno
|
||||||
|
can be checked to distinguish the two cases (if errno is zero, the
|
||||||
|
zlib error is Z_MEM_ERROR). */
|
||||||
|
|
||||||
|
int azdopen(azio_stream *s,File fd, int Flags);
|
||||||
|
/*
|
||||||
|
azdopen() associates a azio_stream with the file descriptor fd. File
|
||||||
|
descriptors are obtained from calls like open, dup, creat, pipe or
|
||||||
|
fileno (in the file has been previously opened with fopen).
|
||||||
|
The mode parameter is as in azopen.
|
||||||
|
The next call of gzclose on the returned azio_stream will also close the
|
||||||
|
file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
|
||||||
|
descriptor fd. If you want to keep fd open, use azdopen(dup(fd), mode).
|
||||||
|
azdopen returns NULL if there was insufficient memory to allocate
|
||||||
|
the (de)compression state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int azread(azio_stream *file, voidp buf, unsigned len);
|
||||||
|
/*
|
||||||
|
Reads the given number of uncompressed bytes from the compressed file.
|
||||||
|
If the input file was not in gzip format, gzread copies the given number
|
||||||
|
of bytes into the buffer.
|
||||||
|
gzread returns the number of uncompressed bytes actually read (0 for
|
||||||
|
end of file, -1 for error). */
|
||||||
|
|
||||||
|
extern int azwrite (azio_stream *file, voidpc buf, unsigned len);
|
||||||
|
/*
|
||||||
|
Writes the given number of uncompressed bytes into the compressed file.
|
||||||
|
gzwrite returns the number of uncompressed bytes actually written
|
||||||
|
(0 in case of error).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int azflush(azio_stream *file, int flush);
|
||||||
|
/*
|
||||||
|
Flushes all pending output into the compressed file. The parameter
|
||||||
|
flush is as in the deflate() function. The return value is the zlib
|
||||||
|
error number (see function gzerror below). gzflush returns Z_OK if
|
||||||
|
the flush parameter is Z_FINISH and all output could be flushed.
|
||||||
|
gzflush should be called only when strictly necessary because it can
|
||||||
|
degrade compression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern z_off_t azseek (azio_stream *file,
|
||||||
|
z_off_t offset, int whence);
|
||||||
|
/*
|
||||||
|
Sets the starting position for the next gzread or gzwrite on the
|
||||||
|
given compressed file. The offset represents a number of bytes in the
|
||||||
|
uncompressed data stream. The whence parameter is defined as in lseek(2);
|
||||||
|
the value SEEK_END is not supported.
|
||||||
|
If the file is opened for reading, this function is emulated but can be
|
||||||
|
extremely slow. If the file is opened for writing, only forward seeks are
|
||||||
|
supported; gzseek then compresses a sequence of zeroes up to the new
|
||||||
|
starting position.
|
||||||
|
|
||||||
|
gzseek returns the resulting offset location as measured in bytes from
|
||||||
|
the beginning of the uncompressed stream, or -1 in case of error, in
|
||||||
|
particular if the file is opened for writing and the new starting position
|
||||||
|
would be before the current position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int azrewind(azio_stream *file);
|
||||||
|
/*
|
||||||
|
Rewinds the given file. This function is supported only for reading.
|
||||||
|
|
||||||
|
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern z_off_t aztell(azio_stream *file);
|
||||||
|
/*
|
||||||
|
Returns the starting position for the next gzread or gzwrite on the
|
||||||
|
given compressed file. This position represents a number of bytes in the
|
||||||
|
uncompressed data stream.
|
||||||
|
|
||||||
|
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int azclose(azio_stream *file);
|
||||||
|
/*
|
||||||
|
Flushes all pending output if necessary, closes the compressed file
|
||||||
|
and deallocates all the (de)compression state. The return value is the zlib
|
||||||
|
error number (see function gzerror below).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Reference in New Issue
Block a user