mariadb/extra/mariabackup/xbstream_read.cc
Vladislav Vaintroub 3d6eb7afcf MDEV-25602 get rid of __WIN__ in favor of standard _WIN32
This fixed the MySQL bug# 20338 about misuse of double underscore
prefix __WIN__, which was old MySQL's idea of identifying Windows
Replace it by _WIN32 standard symbol for targeting Windows OS
(both 32 and 64 bit)

Not that connect storage engine is not fixed in this patch (must be
fixed in "upstream" branch)
2021-06-06 13:21:03 +02:00

226 lines
5.6 KiB
C++

/******************************************************
Copyright (c) 2011-2017 Percona LLC and/or its affiliates.
The xbstream format reader implementation.
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; version 2 of the License.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*******************************************************/
#include <my_global.h>
#include <my_base.h>
#include <zlib.h>
#include "common.h"
#include "xbstream.h"
/* Allocate 1 MB for the payload buffer initially */
#define INIT_BUFFER_LEN (1024 * 1024)
#ifndef MY_OFF_T_MAX
#define MY_OFF_T_MAX (~(my_off_t)0UL)
#endif
struct xb_rstream_struct {
my_off_t offset;
File fd;
};
xb_rstream_t *
xb_stream_read_new(void)
{
xb_rstream_t *stream;
stream = (xb_rstream_t *) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(xb_rstream_t), MYF(MY_FAE));
#ifdef _WIN32
setmode(fileno(stdin), _O_BINARY);
#endif
stream->fd = my_fileno(stdin);
stream->offset = 0;
return stream;
}
static inline
xb_chunk_type_t
validate_chunk_type(uchar code)
{
switch ((xb_chunk_type_t) code) {
case XB_CHUNK_TYPE_PAYLOAD:
case XB_CHUNK_TYPE_EOF:
return (xb_chunk_type_t) code;
default:
return XB_CHUNK_TYPE_UNKNOWN;
}
}
xb_rstream_result_t
xb_stream_validate_checksum(xb_rstream_chunk_t *chunk)
{
ulong checksum;
checksum = my_checksum(0, chunk->data, chunk->length);
if (checksum != chunk->checksum) {
msg("xb_stream_read_chunk(): invalid checksum at offset "
"0x%llx: expected 0x%lx, read 0x%lx.",
(ulonglong) chunk->checksum_offset, chunk->checksum,
checksum);
return XB_STREAM_READ_ERROR;
}
return XB_STREAM_READ_CHUNK;
}
#define F_READ(buf,len) \
do { \
if (xb_read_full(fd, (uchar *)buf, len) < len) { \
msg("xb_stream_read_chunk(): my_read() failed."); \
goto err; \
} \
} while (0)
xb_rstream_result_t
xb_stream_read_chunk(xb_rstream_t *stream, xb_rstream_chunk_t *chunk)
{
uchar tmpbuf[16];
uchar *ptr = tmpbuf;
uint pathlen;
size_t tbytes;
ulonglong ullval;
File fd = stream->fd;
xb_ad(sizeof(tmpbuf) >= CHUNK_HEADER_CONSTANT_LEN);
/* This is the only place where we expect EOF, so read with
xb_read_full() rather than F_READ() */
tbytes = xb_read_full(fd, ptr, CHUNK_HEADER_CONSTANT_LEN);
if (tbytes == 0) {
return XB_STREAM_READ_EOF;
} else if (tbytes < CHUNK_HEADER_CONSTANT_LEN) {
msg("xb_stream_read_chunk(): unexpected end of stream at "
"offset 0x%llx.", stream->offset);
goto err;
}
ptr = tmpbuf;
/* Chunk magic value */
if (memcmp(tmpbuf, XB_STREAM_CHUNK_MAGIC, 8)) {
msg("xb_stream_read_chunk(): wrong chunk magic at offset "
"0x%llx.", (ulonglong) stream->offset);
goto err;
}
ptr += 8;
stream->offset += 8;
/* Chunk flags */
chunk->flags = *ptr++;
stream->offset++;
/* Chunk type, ignore unknown ones if ignorable flag is set */
chunk->type = validate_chunk_type(*ptr);
if (chunk->type == XB_CHUNK_TYPE_UNKNOWN &&
!(chunk->flags & XB_STREAM_FLAG_IGNORABLE)) {
msg("xb_stream_read_chunk(): unknown chunk type 0x%lu at "
"offset 0x%llx.", (ulong) *ptr,
(ulonglong) stream->offset);
goto err;
}
ptr++;
stream->offset++;
/* Path length */
pathlen = uint4korr(ptr);
if (pathlen >= FN_REFLEN) {
msg("xb_stream_read_chunk(): path length (%lu) is too large at "
"offset 0x%llx.", (ulong) pathlen, stream->offset);
goto err;
}
chunk->pathlen = pathlen;
stream->offset +=4;
xb_ad((ptr + 4 - tmpbuf) == CHUNK_HEADER_CONSTANT_LEN);
/* Path */
if (chunk->pathlen > 0) {
F_READ((uchar *) chunk->path, pathlen);
stream->offset += pathlen;
}
chunk->path[pathlen] = '\0';
if (chunk->type == XB_CHUNK_TYPE_EOF) {
return XB_STREAM_READ_CHUNK;
}
/* Payload length */
F_READ(tmpbuf, 16);
ullval = uint8korr(tmpbuf);
if (ullval > (ulonglong) SIZE_T_MAX) {
msg("xb_stream_read_chunk(): chunk length is too large at "
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
ullval);
goto err;
}
chunk->length = (size_t) ullval;
stream->offset += 8;
/* Payload offset */
ullval = uint8korr(tmpbuf + 8);
if (ullval > (ulonglong) MY_OFF_T_MAX) {
msg("xb_stream_read_chunk(): chunk offset is too large at "
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
ullval);
goto err;
}
chunk->offset = (my_off_t) ullval;
stream->offset += 8;
/* Reallocate the buffer if needed */
if (chunk->length > chunk->buflen) {
chunk->data = my_realloc(PSI_NOT_INSTRUMENTED, chunk->data, chunk->length,
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (chunk->data == NULL) {
msg("xb_stream_read_chunk(): failed to increase buffer "
"to %lu bytes.", (ulong) chunk->length);
goto err;
}
chunk->buflen = chunk->length;
}
/* Checksum */
F_READ(tmpbuf, 4);
chunk->checksum = uint4korr(tmpbuf);
chunk->checksum_offset = stream->offset;
/* Payload */
if (chunk->length > 0) {
F_READ(chunk->data, chunk->length);
stream->offset += chunk->length;
}
stream->offset += 4;
return XB_STREAM_READ_CHUNK;
err:
return XB_STREAM_READ_ERROR;
}
int
xb_stream_read_done(xb_rstream_t *stream)
{
my_free(stream);
return 0;
}