int network_mysqld_proto_get_binlog_status(network_packet *packet) { guint8 ok; /* on the network we have a length and packet-number of 4 bytes */ if (0 != network_mysqld_proto_get_int8(packet, &ok)) { return -1; } g_return_val_if_fail(ok == 0, -1); return 0; }
int network_mysqld_proto_get_binlog_event_header(network_packet *packet, network_mysqld_binlog_event *event) { int err = 0; guint8 event_type; err = err || network_mysqld_proto_get_int32(packet, &event->timestamp); err = err || network_mysqld_proto_get_int8(packet, &event_type); err = err || network_mysqld_proto_get_int32(packet, &event->server_id); err = err || network_mysqld_proto_get_int32(packet, &event->event_size); err = err || network_mysqld_proto_get_int32(packet, &event->log_pos); err = err || network_mysqld_proto_get_int16(packet, &event->flags); if (!err) { /* event->event_type is a enum, network_mysqld_proto_get_int8() wants a guint8 ... on x86 a passing the &(enum) down works, on sparc it doesn't */ event->event_type = event_type; } return err ? -1 : 0; }
/** * decode a packet into proto_field according to field->fielddef->type * * @param field field definition * @returns 0 on success, -1 on error */ int network_mysqld_proto_get_myisam_field(network_packet *packet, network_mysqld_myisam_field *field) { guint64 length; guint8 i8; guint16 i16; guint32 i32; guint64 i64; double d; network_mysqld_column *column = field->column; int err = 0; switch ((guchar)column->type) { case MYSQL_TYPE_DOUBLE: /* a DOUBLE is stored in IEEE notation by just copying all 8 bytes */ err = err || (column->max_length != 8); /* has to be 8 bytes */ err = err || (packet->offset + 8 > packet->data->len); if (!err) { memcpy(&d, packet->data->str + packet->offset, 8); err = err || network_mysqld_proto_skip(packet, 8); } if (!err) field->data.f = d; break; case MYSQL_TYPE_TIMESTAMP: /* int4store */ case MYSQL_TYPE_LONG: err = err || network_mysqld_proto_get_int32(packet, &i32); if (!err) field->data.i = i32; break; case MYSQL_TYPE_DATETIME: /* int8store */ case MYSQL_TYPE_LONGLONG: err = err || network_mysqld_proto_get_int64(packet, &i64); if (!err) field->data.i = i64; break; case MYSQL_TYPE_INT24: case MYSQL_TYPE_DATE: /* int3store, a newdate, old-data is 4 byte */ err = err || network_mysqld_proto_get_int24(packet, &i32); if (!err) field->data.i = i32; break; case MYSQL_TYPE_SHORT: err = err || network_mysqld_proto_get_int16(packet, &i16); if (!err) field->data.i = i16; break; case MYSQL_TYPE_TINY: err = err || network_mysqld_proto_get_int8(packet, &i8); if (!err) field->data.i = i8; break; case MYSQL_TYPE_ENUM: switch (column->max_length) { case 1: err = err || network_mysqld_proto_get_int8(packet, &i8); if (!err) field->data.i = i8; break; case 2: err = err || network_mysqld_proto_get_int16(packet, &i16); if (!err) field->data.i = i16; break; default: g_error("%s: enum-length = %lu", G_STRLOC, column->max_length); break; } break; case MYSQL_TYPE_BLOB: switch (column->max_length) { case 1: err = err || network_mysqld_proto_get_int8(packet, &i8); if (!err) length = i8; break; case 2: err = err || network_mysqld_proto_get_int16(packet, &i16); if (!err) length = i16; break; case 3: err = err || network_mysqld_proto_get_int24(packet, &i32); if (!err) length = i32; break; case 4: err = err || network_mysqld_proto_get_int32(packet, &i32); if (!err) length = i32; break; default: /* unknown blob-length */ g_debug_hexdump(G_STRLOC, S(packet->data)); g_error("%s: blob-length = %lu", G_STRLOC, column->max_length); break; } err = err || network_mysqld_proto_get_string_len(packet, &field->data.s, length); break; case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: if (column->max_length < 256) { err = err || network_mysqld_proto_get_int8(packet, &i8); err = err || network_mysqld_proto_get_string_len(packet, &field->data.s, i8); } else { err = err || network_mysqld_proto_get_int16(packet, &i16); err = err || network_mysqld_proto_get_string_len(packet, &field->data.s, i16); } break; case MYSQL_TYPE_NEWDECIMAL: { /* the decimal is binary encoded */ guchar digits_per_bytes[] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 }; /* how many bytes are needed to store x decimal digits */ guint i_digits = column->max_length - column->decimals; guint f_digits = column->decimals; guint decimal_full_blocks = i_digits / 9; /* 9 decimal digits in 4 bytes */ guint decimal_last_block_digits = i_digits % 9; /* how many digits are left ? */ guint scale_full_blocks = f_digits / 9; /* 9 decimal digits in 4 bytes */ guint scale_last_block_digits = f_digits % 9; /* how many digits are left ? */ guint size = 0; size += decimal_full_blocks * digits_per_bytes[9] + digits_per_bytes[decimal_last_block_digits]; size += scale_full_blocks * digits_per_bytes[9] + digits_per_bytes[scale_last_block_digits]; #if 0 g_debug_hexdump(G_STRLOC " (NEWDECIMAL)", packet->data->str, packet->data->len); #endif #if 0 g_critical("%s: don't know how to decode NEWDECIMAL(%lu, %u) at offset %u (%d)", G_STRLOC, column->max_length, column->decimals, packet->offset, size ); #endif err = err || network_mysqld_proto_skip(packet, size); break; } default: g_debug_hexdump(G_STRLOC, packet->data->str, packet->data->len); g_error("%s: unknown field-type to fetch: %d", G_STRLOC, column->type); break; } return err ? -1 : 0; }
int network_mysqld_proto_get_binlog_event(network_packet *packet, network_mysqld_binlog *binlog, network_mysqld_binlog_event *event) { int err = 0; int maj, min, pat; if (binlog->checksum == NETWORK_MYSQLD_BINLOG_CHECKSUM_CRC32) { /* patch the packet-len for the decoders as if there would be no checksum */ packet->data->len -= 4; } switch ((guchar)event->event_type) { case QUERY_EVENT: err = err || network_mysqld_proto_get_int32(packet, &event->event.query_event.thread_id); err = err || network_mysqld_proto_get_int32(packet, &event->event.query_event.exec_time); err = err || network_mysqld_proto_get_int8(packet, &event->event.query_event.db_name_len); err = err || network_mysqld_proto_get_int16(packet, &event->event.query_event.error_code); /* 5.0 has more flags */ if (packet->data->len > packet->offset) { guint16 var_size = 0; err = err || network_mysqld_proto_get_int16(packet, &var_size); if (var_size) { /* skip the variable size part for now */ err = err || network_mysqld_proto_skip(packet, var_size); } /* default db has <db_name_len> chars */ err = err || network_mysqld_proto_get_string_len(packet, &event->event.query_event.db_name, event->event.query_event.db_name_len); err = err || network_mysqld_proto_skip(packet, 1); /* the \0 */ err = err || network_mysqld_proto_get_string_len(packet, &event->event.query_event.query, packet->data->len - packet->offset); } break; case ROTATE_EVENT: err = err || network_mysqld_proto_get_int32(packet, &event->event.rotate_event.binlog_pos); err = err || network_mysqld_proto_skip(packet, 4); err = err || network_mysqld_proto_get_string_len( packet, &event->event.rotate_event.binlog_file, packet->data->len - packet->offset); break; case STOP_EVENT: /* is empty */ break; case FORMAT_DESCRIPTION_EVENT: err = err || network_mysqld_proto_get_int16(packet, &event->event.format_event.binlog_version); err = err || network_mysqld_proto_get_string_len( /* NUL-term string */ packet, &event->event.format_event.master_version, ST_SERVER_VER_LEN); err = err || network_mysqld_proto_get_int32(packet, &event->event.format_event.created_ts); /* the header length may change in the future, for now we assume it is 19 */ err = err || network_mysqld_proto_get_int8(packet, &event->event.format_event.log_header_len); g_assert_cmpint(event->event.format_event.log_header_len, ==, 19); /* decode the server-version string into a integer */ err = err || (3 != sscanf(event->event.format_event.master_version, "%d.%d.%d%*s", &maj, &min, &pat)); err = err || (maj > 100 || maj < 0); err = err || (min > 100 || min < 0); err = err || (pat > 100 || pat < 0); if ((maj << 16) + (min << 8) + (pat << 0) >= 0x050602) { event->event.format_event.perm_events_len = packet->data->len - packet->offset; g_assert_cmpint(event->event.format_event.perm_events_len, ==, ENUM_END_EVENT - 1 + 1 + 4); event->event.format_event.perm_events_len -= 1 + 4; /* FIXME: check how it is implemented without CRC32 */ } else {