Example #1
0
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;
}
Example #2
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;
}
Example #4
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 {