2 azio is a modified version of gzio. It makes use of mysys and removes mallocs.
6 /* gzio.c -- IO on .gz files
7 * Copyright (C) 1995-2005 Jean-loup Gailly.
8 * For conditions of distribution and use, see copyright notice in zlib.h
19 static int const gz_magic
[2] = {0x1f, 0x8b}; /* gzip magic header */
20 static int const az_magic
[3] = {0xfe, 0x03, 0x01}; /* az magic header */
23 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
24 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
25 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
26 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
27 #define COMMENT 0x10 /* bit 4 set: file comment present */
28 #define RESERVED 0xE0 /* bits 5..7: reserved */
30 int az_open(azio_stream
*s
, const char *path
, int Flags
, File fd
);
31 int do_flush(azio_stream
*file
, int flush
);
32 int get_byte(azio_stream
*s
);
33 void check_header(azio_stream
*s
);
34 void write_header(azio_stream
*s
);
35 int destroy(azio_stream
*s
);
36 void putLong(File file
, uLong x
);
37 uLong
getLong(azio_stream
*s
);
38 void read_header(azio_stream
*s
, unsigned char *buffer
);
40 /* ===========================================================================
41 Opens a gzip (.gz) file for reading or writing. The mode parameter
42 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
43 or path name (if fd == -1).
44 az_open returns NULL if the file could not be opened or if there was
45 insufficient memory to allocate the (de)compression state; errno
46 can be checked to distinguish the two cases (if errno is zero, the
47 zlib error is Z_MEM_ERROR).
49 int az_open (azio_stream
*s
, const char *path
, int Flags
, File fd
)
52 int level
= Z_DEFAULT_COMPRESSION
; /* compression level */
53 int strategy
= Z_DEFAULT_STRATEGY
; /* compression strategy */
55 s
->stream
.zalloc
= (alloc_func
)0;
56 s
->stream
.zfree
= (free_func
)0;
57 s
->stream
.opaque
= (voidpf
)0;
58 memset(s
->inbuf
, 0, AZ_BUFSIZE_READ
);
59 memset(s
->outbuf
, 0, AZ_BUFSIZE_WRITE
);
60 s
->stream
.next_in
= s
->inbuf
;
61 s
->stream
.next_out
= s
->outbuf
;
62 s
->stream
.avail_in
= s
->stream
.avail_out
= 0;
68 s
->crc
= crc32(0L, Z_NULL
, 0);
71 s
->version
= (unsigned char)az_magic
[1]; /* this needs to be a define to version */
72 s
->minor_version
= (unsigned char) az_magic
[2]; /* minor version */
73 s
->dirty
= AZ_STATE_CLEAN
;
76 We do our own version of append by nature.
77 We must always have write access to take card of the header.
79 DBUG_ASSERT(Flags
| O_APPEND
);
80 DBUG_ASSERT(Flags
| O_WRONLY
);
87 err
= deflateInit2(&(s
->stream
), level
,
88 Z_DEFLATED
, -MAX_WBITS
, 8, strategy
);
89 /* windowBits is passed < 0 to suppress zlib header */
91 s
->stream
.next_out
= s
->outbuf
;
98 s
->stream
.next_in
= s
->inbuf
;
100 err
= inflateInit2(&(s
->stream
), -MAX_WBITS
);
101 /* windowBits is passed < 0 to tell that there is no zlib header.
102 * Note that in this case inflate *requires* an extra "dummy" byte
103 * after the compressed stream in order to complete decompression and
104 * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
105 * present after the compressed stream.
113 s
->stream
.avail_out
= AZ_BUFSIZE_WRITE
;
116 s
->file
= fd
< 0 ? my_open(path
, Flags
, MYF(0)) : fd
;
117 DBUG_EXECUTE_IF("simulate_archive_open_failure",
121 my_close(s
->file
, MYF(0));
133 if (Flags
& O_CREAT
|| Flags
& O_TRUNC
)
136 s
->forced_flushes
= 0;
139 s
->auto_increment
= 0;
141 s
->comment_start_pos
= 0;
142 s
->comment_length
= 0;
145 s
->dirty
= 1; /* We create the file dirty */
146 s
->start
= AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
;
148 my_seek(s
->file
, 0, MY_SEEK_END
, MYF(0));
150 else if (s
->mode
== 'w')
152 uchar buffer
[AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
];
153 my_pread(s
->file
, buffer
, AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
, 0,
155 read_header(s
, buffer
); /* skip the .az header */
156 my_seek(s
->file
, 0, MY_SEEK_END
, MYF(0));
160 check_header(s
); /* skip the .az header */
167 void write_header(azio_stream
*s
)
169 char buffer
[AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
];
172 s
->block_size
= AZ_BUFSIZE_WRITE
;
173 s
->version
= (unsigned char)az_magic
[1];
174 s
->minor_version
= (unsigned char)az_magic
[2];
177 /* Write a very simple .az header: */
178 memset(buffer
, 0, AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
);
179 *(ptr
+ AZ_MAGIC_POS
)= az_magic
[0];
180 *(ptr
+ AZ_VERSION_POS
)= (unsigned char)s
->version
;
181 *(ptr
+ AZ_MINOR_VERSION_POS
)= (unsigned char)s
->minor_version
;
182 *(ptr
+ AZ_BLOCK_POS
)= (unsigned char)(s
->block_size
/1024); /* Reserved for block size */
183 *(ptr
+ AZ_STRATEGY_POS
)= (unsigned char)Z_DEFAULT_STRATEGY
; /* Compression Type */
185 int4store(ptr
+ AZ_FRM_POS
, s
->frm_start_pos
); /* FRM Block */
186 int4store(ptr
+ AZ_FRM_LENGTH_POS
, s
->frm_length
); /* FRM Block */
187 int4store(ptr
+ AZ_COMMENT_POS
, s
->comment_start_pos
); /* COMMENT Block */
188 int4store(ptr
+ AZ_COMMENT_LENGTH_POS
, s
->comment_length
); /* COMMENT Block */
189 int4store(ptr
+ AZ_META_POS
, 0); /* Meta Block */
190 int4store(ptr
+ AZ_META_LENGTH_POS
, 0); /* Meta Block */
191 int8store(ptr
+ AZ_START_POS
, (unsigned long long)s
->start
); /* Start of Data Block Index Block */
192 int8store(ptr
+ AZ_ROW_POS
, (unsigned long long)s
->rows
); /* Start of Data Block Index Block */
193 int8store(ptr
+ AZ_FLUSH_POS
, (unsigned long long)s
->forced_flushes
); /* Start of Data Block Index Block */
194 int8store(ptr
+ AZ_CHECK_POS
, (unsigned long long)s
->check_point
); /* Start of Data Block Index Block */
195 int8store(ptr
+ AZ_AUTOINCREMENT_POS
, (unsigned long long)s
->auto_increment
); /* Start of Data Block Index Block */
196 int4store(ptr
+ AZ_LONGEST_POS
, s
->longest_row
); /* Longest row */
197 int4store(ptr
+ AZ_SHORTEST_POS
, s
->shortest_row
); /* Shorest row */
198 int4store(ptr
+ AZ_FRM_POS
,
199 AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
); /* FRM position */
200 *(ptr
+ AZ_DIRTY_POS
)= (unsigned char)s
->dirty
; /* Start of Data Block Index Block */
202 /* Always begin at the begining, and end there as well */
203 my_pwrite(s
->file
, (uchar
*) buffer
, AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
, 0,
207 /* ===========================================================================
208 Opens a gzip (.gz) file for reading or writing.
210 int azopen(azio_stream
*s
, const char *path
, int Flags
)
212 return az_open(s
, path
, Flags
, -1);
215 /* ===========================================================================
216 Associate a gzFile with the file descriptor fd. fd is not dup'ed here
217 to mimic the behavio(u)r of fdopen.
219 int azdopen(azio_stream
*s
, File fd
, int Flags
)
221 if (fd
< 0) return 0;
223 return az_open (s
, NULL
, Flags
, fd
);
226 /* ===========================================================================
227 Read a byte from a azio_stream; update next_in and avail_in. Return EOF
229 IN assertion: the stream s has been sucessfully opened for reading.
234 if (s
->z_eof
) return EOF
;
235 if (s
->stream
.avail_in
== 0)
238 s
->stream
.avail_in
= (uInt
) my_read(s
->file
, (uchar
*)s
->inbuf
,
239 AZ_BUFSIZE_READ
, MYF(0));
240 if (s
->stream
.avail_in
== 0)
245 else if (s
->stream
.avail_in
== (uInt
) -1)
251 s
->stream
.next_in
= s
->inbuf
;
253 s
->stream
.avail_in
--;
254 return *(s
->stream
.next_in
)++;
257 /* ===========================================================================
258 Check the gzip header of a azio_stream opened for reading. Set the stream
259 mode to transparent if the gzip magic header is not present; set s->err
260 to Z_DATA_ERROR if the magic header is present but the rest of the header
262 IN assertion: the stream s has already been created sucessfully;
263 s->stream.avail_in is zero for the first time, but may be non-zero
264 for concatenated .gz files.
266 void check_header(azio_stream
*s
)
268 int method
; /* method uchar */
269 int flags
; /* flags uchar */
273 /* Assure two bytes in the buffer so we can peek ahead -- handle case
274 where first byte of header is at the end of the buffer after the last
276 len
= s
->stream
.avail_in
;
278 if (len
) s
->inbuf
[0] = s
->stream
.next_in
[0];
280 len
= (uInt
)my_read(s
->file
, (uchar
*)s
->inbuf
+ len
, AZ_BUFSIZE_READ
>> len
, MYF(0));
281 if (len
== (uInt
)-1) s
->z_err
= Z_ERRNO
;
282 s
->stream
.avail_in
+= len
;
283 s
->stream
.next_in
= s
->inbuf
;
284 if (s
->stream
.avail_in
< 2) {
285 s
->transparent
= s
->stream
.avail_in
;
290 /* Peek ahead to check the gzip magic header */
291 if ( s
->stream
.next_in
[0] == gz_magic
[0] && s
->stream
.next_in
[1] == gz_magic
[1])
293 s
->stream
.avail_in
-= 2;
294 s
->stream
.next_in
+= 2;
295 s
->version
= (unsigned char)2;
297 /* Check the rest of the gzip header */
298 method
= get_byte(s
);
300 if (method
!= Z_DEFLATED
|| (flags
& RESERVED
) != 0) {
301 s
->z_err
= Z_DATA_ERROR
;
305 /* Discard time, xflags and OS code: */
306 for (len
= 0; len
< 6; len
++) (void)get_byte(s
);
308 if ((flags
& EXTRA_FIELD
) != 0) { /* skip the extra field */
309 len
= (uInt
)get_byte(s
);
310 len
+= ((uInt
)get_byte(s
))<<8;
311 /* len is garbage if EOF but the loop below will quit anyway */
312 while (len
-- != 0 && get_byte(s
) != EOF
) ;
314 if ((flags
& ORIG_NAME
) != 0) { /* skip the original file name */
315 while ((c
= get_byte(s
)) != 0 && c
!= EOF
) ;
317 if ((flags
& COMMENT
) != 0) { /* skip the .gz file comment */
318 while ((c
= get_byte(s
)) != 0 && c
!= EOF
) ;
320 if ((flags
& HEAD_CRC
) != 0) { /* skip the header crc */
321 for (len
= 0; len
< 2; len
++) (void)get_byte(s
);
323 s
->z_err
= s
->z_eof
? Z_DATA_ERROR
: Z_OK
;
324 s
->start
= my_tell(s
->file
, MYF(0)) - s
->stream
.avail_in
;
326 else if ( s
->stream
.next_in
[0] == az_magic
[0] && s
->stream
.next_in
[1] == az_magic
[1])
328 unsigned char buffer
[AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
];
330 for (len
= 0; len
< (AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
); len
++)
331 buffer
[len
]= get_byte(s
);
332 s
->z_err
= s
->z_eof
? Z_DATA_ERROR
: Z_OK
;
333 read_header(s
, buffer
);
334 for (; len
< s
->start
; len
++)
345 void read_header(azio_stream
*s
, unsigned char *buffer
)
347 if (buffer
[0] == az_magic
[0] && buffer
[1] == az_magic
[1])
349 s
->version
= (unsigned int)buffer
[AZ_VERSION_POS
];
350 s
->minor_version
= (unsigned int)buffer
[AZ_MINOR_VERSION_POS
];
351 s
->block_size
= 1024 * buffer
[AZ_BLOCK_POS
];
352 s
->start
= (unsigned long long)uint8korr(buffer
+ AZ_START_POS
);
353 s
->rows
= (unsigned long long)uint8korr(buffer
+ AZ_ROW_POS
);
354 s
->check_point
= (unsigned long long)uint8korr(buffer
+ AZ_CHECK_POS
);
355 s
->forced_flushes
= (unsigned long long)uint8korr(buffer
+ AZ_FLUSH_POS
);
356 s
->auto_increment
= (unsigned long long)uint8korr(buffer
+ AZ_AUTOINCREMENT_POS
);
357 s
->longest_row
= (unsigned int)uint4korr(buffer
+ AZ_LONGEST_POS
);
358 s
->shortest_row
= (unsigned int)uint4korr(buffer
+ AZ_SHORTEST_POS
);
359 s
->frm_start_pos
= (unsigned int)uint4korr(buffer
+ AZ_FRM_POS
);
360 s
->frm_length
= (unsigned int)uint4korr(buffer
+ AZ_FRM_LENGTH_POS
);
361 s
->comment_start_pos
= (unsigned int)uint4korr(buffer
+ AZ_COMMENT_POS
);
362 s
->comment_length
= (unsigned int)uint4korr(buffer
+ AZ_COMMENT_LENGTH_POS
);
363 s
->dirty
= (unsigned int)buffer
[AZ_DIRTY_POS
];
365 else if (buffer
[0] == gz_magic
[0] && buffer
[1] == gz_magic
[1])
368 Set version number to previous version (2).
370 s
->version
= (unsigned char) 2;
374 Most probably due to a corrupt archive.
376 s
->dirty
= AZ_STATE_DIRTY
;
377 s
->z_err
= Z_VERSION_ERROR
;
381 /* ===========================================================================
382 * Cleanup then free the given azio_stream. Return a zlib error code.
383 Try freeing in the reverse order of allocations.
390 if (s
->stream
.state
!= NULL
)
393 err
= deflateEnd(&(s
->stream
));
394 else if (s
->mode
== 'r')
395 err
= inflateEnd(&(s
->stream
));
398 if (s
->file
> 0 && my_close(s
->file
, MYF(0)))
403 if (s
->z_err
< 0) err
= s
->z_err
;
408 /* ===========================================================================
409 Reads the given number of uncompressed bytes from the compressed file.
410 azread returns the number of bytes actually read (0 for end of file).
412 unsigned int ZEXPORT
azread ( azio_stream
*s
, voidp buf
, size_t len
, int *error
)
414 Bytef
*start
= (Bytef
*)buf
; /* starting point for crc computation */
415 Byte
*next_out
; /* == stream.next_out but not forced far (for MSDOS) */
420 *error
= Z_STREAM_ERROR
;
424 if (s
->z_err
== Z_DATA_ERROR
|| s
->z_err
== Z_ERRNO
)
430 if (s
->z_err
== Z_STREAM_END
) /* EOF */
435 next_out
= (Byte
*)buf
;
436 s
->stream
.next_out
= (Bytef
*)buf
;
437 s
->stream
.avail_out
= len
;
439 if (s
->stream
.avail_out
&& s
->back
!= EOF
) {
440 *next_out
++ = s
->back
;
441 s
->stream
.next_out
++;
442 s
->stream
.avail_out
--;
447 s
->z_err
= Z_STREAM_END
;
454 while (s
->stream
.avail_out
!= 0) {
456 if (s
->transparent
) {
457 /* Copy first the lookahead bytes: */
458 uInt n
= s
->stream
.avail_in
;
459 if (n
> s
->stream
.avail_out
) n
= s
->stream
.avail_out
;
461 memcpy(s
->stream
.next_out
, s
->stream
.next_in
, n
);
463 s
->stream
.next_out
= (Bytef
*)next_out
;
464 s
->stream
.next_in
+= n
;
465 s
->stream
.avail_out
-= n
;
466 s
->stream
.avail_in
-= n
;
468 if (s
->stream
.avail_out
> 0)
470 s
->stream
.avail_out
-=
471 (uInt
)my_read(s
->file
, (uchar
*)next_out
, s
->stream
.avail_out
, MYF(0));
473 len
-= s
->stream
.avail_out
;
476 if (len
== 0) s
->z_eof
= 1;
481 if (s
->stream
.avail_in
== 0 && !s
->z_eof
) {
484 s
->stream
.avail_in
= (uInt
)my_read(s
->file
, (uchar
*)s
->inbuf
, AZ_BUFSIZE_READ
, MYF(0));
485 if (s
->stream
.avail_in
== 0)
489 s
->stream
.next_in
= (Bytef
*)s
->inbuf
;
491 s
->in
+= s
->stream
.avail_in
;
492 s
->out
+= s
->stream
.avail_out
;
493 s
->z_err
= inflate(&(s
->stream
), Z_NO_FLUSH
);
494 s
->in
-= s
->stream
.avail_in
;
495 s
->out
-= s
->stream
.avail_out
;
497 if (s
->z_err
== Z_STREAM_END
) {
498 /* Check CRC and original size */
499 s
->crc
= crc32(s
->crc
, start
, (uInt
)(s
->stream
.next_out
- start
));
500 start
= s
->stream
.next_out
;
502 if (getLong(s
) != s
->crc
) {
503 s
->z_err
= Z_DATA_ERROR
;
506 /* The uncompressed length returned by above getlong() may be
507 * different from s->out in case of concatenated .gz files.
508 * Check for such files:
511 if (s
->z_err
== Z_OK
)
513 inflateReset(&(s
->stream
));
514 s
->crc
= crc32(0L, Z_NULL
, 0);
518 if (s
->z_err
!= Z_OK
|| s
->z_eof
) break;
520 s
->crc
= crc32(s
->crc
, start
, (uInt
)(s
->stream
.next_out
- start
));
522 if (len
== s
->stream
.avail_out
&&
523 (s
->z_err
== Z_DATA_ERROR
|| s
->z_err
== Z_ERRNO
))
530 return (len
- s
->stream
.avail_out
);
534 /* ===========================================================================
535 Writes the given number of uncompressed bytes into the compressed file.
536 azwrite returns the number of bytes actually written (0 in case of error).
538 unsigned int azwrite (azio_stream
*s
, const voidp buf
, unsigned int len
)
540 s
->stream
.next_in
= (Bytef
*)buf
;
541 s
->stream
.avail_in
= len
;
545 while (s
->stream
.avail_in
!= 0)
547 if (s
->stream
.avail_out
== 0)
550 s
->stream
.next_out
= s
->outbuf
;
551 if (my_write(s
->file
, (uchar
*)s
->outbuf
, AZ_BUFSIZE_WRITE
,
552 MYF(0)) != AZ_BUFSIZE_WRITE
)
557 s
->stream
.avail_out
= AZ_BUFSIZE_WRITE
;
559 s
->in
+= s
->stream
.avail_in
;
560 s
->out
+= s
->stream
.avail_out
;
561 s
->z_err
= deflate(&(s
->stream
), Z_NO_FLUSH
);
562 s
->in
-= s
->stream
.avail_in
;
563 s
->out
-= s
->stream
.avail_out
;
564 if (s
->z_err
!= Z_OK
) break;
566 s
->crc
= crc32(s
->crc
, (const Bytef
*)buf
, len
);
568 if (len
> s
->longest_row
)
571 if (len
< s
->shortest_row
|| !(s
->shortest_row
))
572 s
->shortest_row
= len
;
574 return (unsigned int)(len
- s
->stream
.avail_in
);
578 /* ===========================================================================
579 Flushes all pending output into the compressed file. The parameter
580 flush is as in the deflate() function.
582 int do_flush (azio_stream
*s
, int flush
)
586 my_off_t afterwrite_pos
;
588 if (s
== NULL
|| s
->mode
!= 'w') return Z_STREAM_ERROR
;
590 s
->stream
.avail_in
= 0; /* should be zero already anyway */
594 len
= AZ_BUFSIZE_WRITE
- s
->stream
.avail_out
;
598 s
->check_point
= my_tell(s
->file
, MYF(0));
599 if ((uInt
)my_write(s
->file
, (uchar
*)s
->outbuf
, len
, MYF(0)) != len
)
604 s
->stream
.next_out
= s
->outbuf
;
605 s
->stream
.avail_out
= AZ_BUFSIZE_WRITE
;
608 s
->out
+= s
->stream
.avail_out
;
609 s
->z_err
= deflate(&(s
->stream
), flush
);
610 s
->out
-= s
->stream
.avail_out
;
612 /* Ignore the second of two consecutive flushes: */
613 if (len
== 0 && s
->z_err
== Z_BUF_ERROR
) s
->z_err
= Z_OK
;
615 /* deflate has finished flushing only when it hasn't used up
616 * all the available space in the output buffer:
618 done
= (s
->stream
.avail_out
!= 0 || s
->z_err
== Z_STREAM_END
);
620 if (s
->z_err
!= Z_OK
&& s
->z_err
!= Z_STREAM_END
) break;
623 if (flush
== Z_FINISH
)
624 s
->dirty
= AZ_STATE_CLEAN
; /* Mark it clean, we should be good now */
626 s
->dirty
= AZ_STATE_SAVED
; /* Mark it clean, we should be good now */
628 afterwrite_pos
= my_tell(s
->file
, MYF(0));
630 my_seek(s
->file
, afterwrite_pos
, SEEK_SET
, MYF(0));
632 return s
->z_err
== Z_STREAM_END
? Z_OK
: s
->z_err
;
635 int ZEXPORT
azflush (s
, flush
)
643 unsigned char buffer
[AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
];
644 my_pread(s
->file
, (uchar
*) buffer
, AZHEADER_SIZE
+ AZMETA_BUFFER_SIZE
, 0,
646 read_header(s
, buffer
); /* skip the .az header */
653 err
= do_flush(s
, flush
);
656 my_sync(s
->file
, MYF(0));
657 return s
->z_err
== Z_STREAM_END
? Z_OK
: s
->z_err
;
661 /* ===========================================================================
667 if (s
== NULL
|| s
->mode
!= 'r') return -1;
672 s
->stream
.avail_in
= 0;
673 s
->stream
.next_in
= (Bytef
*)s
->inbuf
;
674 s
->crc
= crc32(0L, Z_NULL
, 0);
675 if (!s
->transparent
) (void)inflateReset(&s
->stream
);
678 return my_seek(s
->file
, (int)s
->start
, MY_SEEK_SET
, MYF(0)) == MY_FILEPOS_ERROR
;
681 /* ===========================================================================
682 Sets the starting position for the next azread or azwrite on the given
683 compressed file. The offset represents a number of bytes in the
684 azseek returns the resulting offset location as measured in bytes from
685 the beginning of the uncompressed stream, or -1 in case of error.
686 SEEK_END is not implemented, returns error.
687 In this version of the library, azseek can be extremely slow.
689 my_off_t
azseek (s
, offset
, whence
)
695 if (s
== NULL
|| whence
== SEEK_END
||
696 s
->z_err
== Z_ERRNO
|| s
->z_err
== Z_DATA_ERROR
) {
702 if (whence
== SEEK_SET
)
705 /* At this point, offset is the number of zero bytes to write. */
706 /* There was a zmemzero here if inbuf was null -Brian */
709 uInt size
= AZ_BUFSIZE_READ
;
710 if (offset
< AZ_BUFSIZE_READ
) size
= (uInt
)offset
;
712 size
= azwrite(s
, s
->inbuf
, size
);
713 if (size
== 0) return -1L;
719 /* Rest of function is for reading only */
721 /* compute absolute position */
722 if (whence
== SEEK_CUR
) {
726 if (s
->transparent
) {
729 s
->stream
.avail_in
= 0;
730 s
->stream
.next_in
= (Bytef
*)s
->inbuf
;
731 if (my_seek(s
->file
, offset
, MY_SEEK_SET
, MYF(0)) == MY_FILEPOS_ERROR
) return -1L;
733 s
->in
= s
->out
= offset
;
737 /* For a negative seek, rewind and use positive seek */
738 if (offset
>= s
->out
) {
740 } else if (azrewind(s
)) {
743 /* offset is now the number of bytes to skip. */
745 if (offset
&& s
->back
!= EOF
) {
749 if (s
->last
) s
->z_err
= Z_STREAM_END
;
753 unsigned int size
= AZ_BUFSIZE_WRITE
;
754 if (offset
< AZ_BUFSIZE_WRITE
) size
= (int)offset
;
756 size
= azread(s
, s
->outbuf
, size
, &error
);
757 if (error
< 0) return -1L;
763 /* ===========================================================================
764 Returns the starting position for the next azread or azwrite on the
765 given compressed file. This position represents a number of bytes in the
766 uncompressed data stream.
768 my_off_t ZEXPORT
aztell (file
)
771 return azseek(file
, 0L, SEEK_CUR
);
775 /* ===========================================================================
776 Outputs a long in LSB order to the given file
778 void putLong (File file
, uLong x
)
783 for (n
= 0; n
< 4; n
++)
785 buffer
[0]= (int)(x
& 0xff);
786 my_write(file
, buffer
, 1, MYF(0));
791 /* ===========================================================================
792 Reads a long in LSB order from the given azio_stream. Sets z_err in case
795 uLong
getLong (azio_stream
*s
)
797 uLong x
= (uLong
)get_byte(s
);
800 x
+= ((uLong
)get_byte(s
))<<8;
801 x
+= ((uLong
)get_byte(s
))<<16;
803 if (c
== EOF
) s
->z_err
= Z_DATA_ERROR
;
808 /* ===========================================================================
809 Flushes all pending output if necessary, closes the compressed file
810 and deallocates all the (de)compression state.
812 int azclose (azio_stream
*s
)
815 if (s
== NULL
) return Z_STREAM_ERROR
;
817 if (s
->file
< 1) return Z_OK
;
821 if (do_flush(s
, Z_FINISH
) != Z_OK
)
824 putLong(s
->file
, s
->crc
);
825 putLong(s
->file
, (uLong
)(s
->in
& 0xffffffff));
826 s
->dirty
= AZ_STATE_CLEAN
;
827 s
->check_point
= my_tell(s
->file
, MYF(0));
835 Though this was added to support MySQL's FRM file, anything can be
836 stored in this location.
838 int azwrite_frm(azio_stream
*s
, char *blob
, unsigned int length
)
846 s
->frm_start_pos
= (uint
) s
->start
;
847 s
->frm_length
= length
;
850 my_pwrite(s
->file
, (uchar
*) blob
, s
->frm_length
, s
->frm_start_pos
, MYF(0));
853 my_seek(s
->file
, 0, MY_SEEK_END
, MYF(0));
858 int azread_frm(azio_stream
*s
, char *blob
)
860 my_pread(s
->file
, (uchar
*) blob
, s
->frm_length
, s
->frm_start_pos
, MYF(0));
869 int azwrite_comment(azio_stream
*s
, char *blob
, unsigned int length
)
877 s
->comment_start_pos
= (uint
) s
->start
;
878 s
->comment_length
= length
;
881 my_pwrite(s
->file
, (uchar
*) blob
, s
->comment_length
, s
->comment_start_pos
,
885 my_seek(s
->file
, 0, MY_SEEK_END
, MYF(0));
890 int azread_comment(azio_stream
*s
, char *blob
)
892 my_pread(s
->file
, (uchar
*) blob
, s
->comment_length
, s
->comment_start_pos
,