1
/******************************************************
2
Copyright (c) 2011 Percona Inc.
4
The xbstream format reader implementation.
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; version 2 of the License.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*******************************************************/
26
/* Allocate 1 MB for the payload buffer initially */
27
#define INIT_BUFFER_LEN (1024 * 1024)
30
#define MY_OFF_T_MAX (~(my_off_t)0UL)
33
struct xb_rstream_struct {
41
xb_stream_read_new(void)
45
stream = (xb_rstream_t *) my_malloc(sizeof(xb_rstream_t), MYF(MY_FAE));
47
stream->buffer = my_malloc(INIT_BUFFER_LEN, MYF(MY_FAE));
48
stream->buflen = INIT_BUFFER_LEN;
50
stream->fd = fileno(stdin);
54
setmode(stream->fd, _O_BINARY);
62
validate_chunk_type(uchar code)
64
switch ((xb_chunk_type_t) code) {
65
case XB_CHUNK_TYPE_PAYLOAD:
66
case XB_CHUNK_TYPE_EOF:
67
return (xb_chunk_type_t) code;
69
return XB_CHUNK_TYPE_UNKNOWN;
73
#define F_READ(buf,len) \
75
if (my_read(fd, buf, len, MYF(MY_WME|MY_FULL_IO)) == \
77
msg("xb_stream_read_chunk(): my_read() failed.\n"); \
83
xb_stream_read_chunk(xb_rstream_t *stream, xb_rstream_chunk_t *chunk)
94
/* This is the only place where we expect EOF, so read with my_read()
95
rather than F_READ() */
96
tlen = my_read(fd, tmpbuf, sizeof(XB_STREAM_CHUNK_MAGIC) + 5,
99
return XB_STREAM_READ_EOF;
100
} else if (tlen < sizeof(XB_STREAM_CHUNK_MAGIC) + 4) {
101
msg("xb_stream_read_chunk(): unexpected end of stream at "
102
"offset 0x%llx.\n", stream->offset);
106
/* Chunk magic value */
107
if (memcmp(tmpbuf, XB_STREAM_CHUNK_MAGIC, 8)) {
108
msg("xb_stream_read_chunk(): wrong chunk magic at offset "
109
"0x%llx.\n", (ulonglong) stream->offset);
116
chunk->flags = *ptr++;
119
/* Chunk type, ignore unknown ones if ignorable flag is set */
120
chunk->type = validate_chunk_type(*ptr);
121
if (chunk->type == XB_CHUNK_TYPE_UNKNOWN &&
122
!(chunk->flags & XB_STREAM_FLAG_IGNORABLE)) {
123
msg("xb_stream_read_chunk(): unknown chunk type 0x%lu at "
124
"offset 0x%llx.\n", (ulong) *ptr,
125
(ulonglong) stream->offset);
132
pathlen = uint4korr(ptr);
133
if (pathlen >= FN_REFLEN) {
134
msg("xb_stream_read_chunk(): path length (%lu) is too large at "
135
"offset 0x%llx.\n", (ulong) pathlen, stream->offset);
138
chunk->pathlen = pathlen;
142
if (chunk->pathlen > 0) {
143
F_READ((uchar *) chunk->path, pathlen);
144
stream->offset += pathlen;
146
chunk->path[pathlen] = '\0';
148
if (chunk->type == XB_CHUNK_TYPE_EOF) {
149
return XB_STREAM_READ_CHUNK;
154
ullval = uint8korr(tmpbuf);
155
if (ullval > (ulonglong) SIZE_T_MAX) {
156
msg("xb_stream_read_chunk(): chunk length is too large at "
157
"offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset,
161
chunk->length = (size_t) ullval;
165
ullval = uint8korr(tmpbuf + 8);
166
if (ullval > (ulonglong) MY_OFF_T_MAX) {
167
msg("xb_stream_read_chunk(): chunk offset is too large at "
168
"offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset,
172
chunk->offset = (my_off_t) ullval;
175
/* Reallocate the buffer if needed */
176
if (chunk->length > stream->buflen) {
177
stream->buffer = my_realloc(stream->buffer, chunk->length,
179
if (stream->buffer == NULL) {
180
msg("xb_stream_read_chunk(): failed to increase buffer "
181
"to %lu bytes.\n", (ulong) chunk->length);
184
stream->buflen = chunk->length;
189
checksum_exp = uint4korr(tmpbuf);
192
if (chunk->length > 0) {
193
F_READ(stream->buffer, chunk->length);
194
stream->offset += chunk->length;
197
checksum = crc32(0, stream->buffer, chunk->length);
198
if (checksum != checksum_exp) {
199
msg("xb_stream_read_chunk(): invalid checksum at offset "
200
"0x%llx: expected 0x%lx, read 0x%lx.\n",
201
(ulonglong) stream->offset, checksum_exp, checksum);
206
chunk->data = stream->buffer;
207
chunk->checksum = checksum;
209
return XB_STREAM_READ_CHUNK;
212
return XB_STREAM_READ_ERROR;
216
xb_stream_read_done(xb_rstream_t *stream)
218
MY_FREE(stream->buffer);