diff options
author | unknown <brian@zim.(none)> | 2005-12-22 20:06:05 -0800 |
---|---|---|
committer | unknown <brian@zim.(none)> | 2005-12-22 20:06:05 -0800 |
commit | 2c88b6395b6343a3849ef0d3cb932ce7f9c282d3 (patch) | |
tree | c40d75178198f63434dbb904677d9fa2411ab2de /storage | |
parent | 2f7d04166534c7ac7962096045136385cf573703 (diff) | |
parent | 93b3d4efc6c172b1cbc5cca35fa9b10a1aa12fb5 (diff) | |
download | mariadb-git-2c88b6395b6343a3849ef0d3cb932ce7f9c282d3.tar.gz |
Merge baker@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into zim.(none):/home/brian/mysql/archive-5.1
configure.in:
Auto merged
libmysqld/Makefile.am:
Auto merged
sql/Makefile.am:
Auto merged
sql/ha_archive.cc:
Auto merged
storage/Makefile.am:
Hand merge of the Makefile.am changes (I assume Antony pushed loadable).
Diffstat (limited to 'storage')
-rw-r--r-- | storage/Makefile.am | 2 | ||||
-rw-r--r-- | storage/archive/Makefile.am | 31 | ||||
-rw-r--r-- | storage/archive/archive_test.c | 48 | ||||
-rw-r--r-- | storage/archive/azio.c | 653 | ||||
-rw-r--r-- | storage/archive/azlib.h | 278 |
5 files changed, 1011 insertions, 1 deletions
diff --git a/storage/Makefile.am b/storage/Makefile.am index 7b6f50b4f33..95c49b50890 100644 --- a/storage/Makefile.am +++ b/storage/Makefile.am @@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = SUBDIRS = -DIST_SUBDIRS = . csv example bdb heap innobase myisam myisammrg ndb +DIST_SUBDIRS = . csv example bdb heap innobase myisam myisammrg ndb archive # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/storage/archive/Makefile.am b/storage/archive/Makefile.am new file mode 100644 index 00000000000..fabeca81eda --- /dev/null +++ b/storage/archive/Makefile.am @@ -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.% diff --git a/storage/archive/archive_test.c b/storage/archive/archive_test.c new file mode 100644 index 00000000000..5e3a60b606d --- /dev/null +++ b/storage/archive/archive_test.c @@ -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; +} diff --git a/storage/archive/azio.c b/storage/archive/azio.c new file mode 100644 index 00000000000..4a08f65ff30 --- /dev/null +++ b/storage/archive/azio.c @@ -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); +} diff --git a/storage/archive/azlib.h b/storage/archive/azlib.h new file mode 100644 index 00000000000..0c2daaea940 --- /dev/null +++ b/storage/archive/azlib.h @@ -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 |