示例#1
0
static void 
create_record(char *record, uint rownr)
{
	char           *pos;
	bzero((char *)record, MAX_REC_LENGTH);
	record[0] = 1;		/* delete marker */
	if (rownr == 0 && keyinfo[0].seg[0].null_bit)
		record[0] |= keyinfo[0].seg[0].null_bit;	/* Null key */

	pos = record + 1;
	if (recinfo[1].type == FIELD_BLOB) {
		uint		tmp;
		char           *ptr;
		create_key_part(blob_key, rownr);
		tmp = strlen(blob_key);
		int4store(pos, tmp);
		ptr = blob_key;
		memcpy_fixed(pos + 4, &ptr, sizeof(char *));
		pos += recinfo[1].length;
	} else if (recinfo[1].type == FIELD_VARCHAR) {
		uint		tmp;
		create_key_part(pos + 2, rownr);
		tmp = strlen(pos + 2);
		int2store(pos, tmp);
		pos += recinfo[1].length;
	} else {
		create_key_part(pos, rownr);
		pos += recinfo[1].length;
	}
	if (recinfo[2].type == FIELD_BLOB) {
		uint		tmp;
		char           *ptr;;
		sprintf(blob_record, "... row: %d", rownr);
		strappend(blob_record, max(MAX_REC_LENGTH - rownr, 10), ' ');
		tmp = strlen(blob_record);
		int4store(pos, tmp);
		ptr = blob_record;
		memcpy_fixed(pos + 4, &ptr, sizeof(char *));
	} else if (recinfo[2].type == FIELD_VARCHAR) {
		uint		tmp;
		sprintf(pos + 2, "... row: %d", rownr);
		tmp = strlen(pos + 2);
		int2store(pos, tmp);
	} else {
		sprintf(pos, "... row: %d", rownr);
		strappend(pos, recinfo[2].length, ' ');
	}
}
示例#2
0
文件: pack.c 项目: knielsen/mariadb
uchar *safe_net_store_length(uchar *packet, size_t packet_len, ulonglong length)
{
  if (length < 251)
  {
    if (packet_len < 1)
      return NULL;
    *packet= (uchar) length;
    return packet+1;
  }
  /* 251 is reserved for NULL */
  if (length < 65536)
  {
    if (packet_len < 3)
      return NULL;
    *packet++=252;
    int2store(packet, (uint) length);
    return packet+2;
  }
  if (length < 16777216)
  {
    if (packet_len < 4)
      return NULL;
    *packet++=253;
    int3store(packet, (ulong) length);
    return packet+3;
  }
  if (packet_len < 9)
    return NULL;
  *packet++=254;
  int8store(packet,length);
  return packet+8;
}
示例#3
0
/* {{{ mysqlnd_com_set_option_run */
enum_func_status
mysqlnd_com_set_option_run(void *cmd)
{
	struct st_mysqlnd_protocol_com_set_option_command * command = (struct st_mysqlnd_protocol_com_set_option_command *) cmd;
	zend_uchar buffer[2];
	enum_func_status ret = FAIL;
	MYSQLND_CONN_DATA * conn = command->context.conn;
	enum_mysqlnd_server_option option = command->context.option;
	func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
	func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;

	DBG_ENTER("mysqlnd_com_set_option_run");
	int2store(buffer, (unsigned int) option);

	ret = send_command(conn->payload_decoder_factory, COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
					   &conn->state,
					   conn->error_info,
					   conn->upsert_status,
					   conn->stats,
					   conn->m->send_close,
					   conn);
	if (PASS == ret) {
		ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE,
		                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
	}
	DBG_RETURN(ret);
}
static 
void 
doTransaction_T4(Ndb * pNDB, ThreadData * td, int async)
{
   /*----------------*/
   /* Init arguments */
   /*----------------*/
  getRandomSubscriberNumber(td->transactionData.number);
  getRandomServerId(&td->transactionData.server_id);
  
  td->transactionData.server_bit = (1 << td->transactionData.server_id);
  td->transactionData.do_rollback = 
    getNextRandom(&td->generator.rollbackSequenceT4);

  memset(td->transactionData.session_details+2, 
	 myRandom48(26)+'A', SESSION_DETAILS_LENGTH-3);
  td->transactionData.session_details[SESSION_DETAILS_LENGTH-1] = 0;
  int2store(td->transactionData.session_details,SESSION_DETAILS_LENGTH-2);
  
  /*-----------------*/
  /* Run transaction */
  /*-----------------*/
  td->runState = Running;
  td->generator.transactions[3].startLatency();
  start_T4(pNDB, td, async);
}
示例#5
0
static int send_change_user_packet(MCPVIO_EXT *mpvio,
                                   const uchar *data, int data_len)
{
    MYSQL *mysql= mpvio->mysql;
    char *buff, *end;
    int res= 1;
    size_t conn_attr_len= (mysql->options.extension) ?
                          mysql->options.extension->connect_attrs_len : 0;

    buff= my_alloca(USERNAME_LENGTH+1 + data_len+1 + NAME_LEN+1 + 2 + NAME_LEN+1 + 9 + conn_attr_len);

    end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;

    if (!data_len)
        *end++= 0;
    else
    {
        if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
        {
            DBUG_ASSERT(data_len <= 255);
            if (data_len > 255)
            {
                my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
                goto error;
            }
            *end++= data_len;
        }
        else
        {
            DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
            DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
        }
        memcpy(end, data, data_len);
        end+= data_len;
    }
    end= strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;

    if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
    {
        int2store(end, (ushort) mysql->charset->nr);
        end+= 2;
    }

    if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
        end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;

    end= ma_send_connect_attr(mysql, end);

    res= simple_command(mysql, MYSQL_COM_CHANGE_USER,
                        buff, (ulong)(end-buff), 1, NULL);

error:
    my_afree(buff);
    return res;
}
示例#6
0
void _nisam_log_command(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length, int result)
{
  char buff[9];
  int error,old_errno;
  ulong pid=(ulong) GETPID();

  old_errno=my_errno;
  buff[0]=(char) command;
  int2store(buff+1,info->dfile);
  int4store(buff+3,pid);
  int2store(buff+7,result);
  pthread_mutex_lock(&THR_LOCK_isam);
  error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
  VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
  if (buffert)
    VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
  if (!error)
    error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
  pthread_mutex_unlock(&THR_LOCK_isam);
  my_errno=old_errno;
}
示例#7
0
void _nisam_log_record(enum nisam_log_commands command, N_INFO *info, const byte *record, ulong filepos, int result)
{
  char buff[17],*pos;
  int error,old_errno;
  uint length;
  ulong pid=(ulong) GETPID();

  old_errno=my_errno;
  if (!info->s->base.blobs)
    length=info->s->base.reclength;
  else
    length=info->s->base.reclength+ _calc_total_blob_length(info,record);
  buff[0]=(char) command;
  int2store(buff+1,info->dfile);
  int4store(buff+3,pid);
  int2store(buff+7,result);
  int4store(buff+9,filepos);
  int4store(buff+13,length);
  pthread_mutex_lock(&THR_LOCK_isam);
  error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
  VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
  VOID(my_write(nisam_log_file,(byte*) record,info->s->base.reclength,MYF(0)));
  if (info->s->base.blobs)
  {
    N_BLOB *blob,*end;

    for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
	 blob != end ;
	 blob++)
    {
      bmove(&pos,record+blob->offset+blob->pack_length,sizeof(char*));
      VOID(my_write(nisam_log_file,pos,blob->length,MYF(0)));
    }
  }
  if (!error)
    error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
  pthread_mutex_unlock(&THR_LOCK_isam);
  my_errno=old_errno;
}
示例#8
0
static void 
update_record(char *record)
{
	char           *pos = record + 1;
	if (recinfo[1].type == FIELD_BLOB) {
		char           *column, *ptr;
		int		length;
		length = uint4korr(pos);	/* Long blob */
		memcpy_fixed(&column, pos + 4, sizeof(char *));
		memcpy(blob_key, column, length);	/* Move old key */
		ptr = blob_key;
		memcpy_fixed(pos + 4, &ptr, sizeof(char *));	/* Store pointer to new
								 * key */
		if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
			casedn(blob_key, length);
		pos += recinfo[1].length;
	} else if (recinfo[1].type == FIELD_VARCHAR) {
		uint		length = uint2korr(pos);
		casedn(pos + 2, length);
		pos += recinfo[1].length;
	} else {
		if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
			casedn(pos, keyinfo[0].seg[0].length);
		pos += recinfo[1].length;
	}

	if (recinfo[2].type == FIELD_BLOB) {
		char           *column;
		int		length;
		length = uint4korr(pos);
		memcpy_fixed(&column, pos + 4, sizeof(char *));
		memcpy(blob_record, column, length);
		bfill(blob_record + length, 20, '.');	/* Make it larger */
		length += 20;
		int4store(pos, length);
		column = blob_record;
		memcpy_fixed(pos + 4, &column, sizeof(char *));
	} else if (recinfo[2].type == FIELD_VARCHAR) {
		/* Second field is longer than 10 characters */
		uint		length = uint2korr(pos);
		bfill(pos + 2 + length, recinfo[2].length - length - 2, '.');
		length = recinfo[2].length - 2;
		int2store(pos, length);
	} else {
		bfill(pos + recinfo[2].length - 10, 10, '.');
	}
}
uint _ft_make_key(MI_INFO *info, uint keynr, uchar *keybuf, FT_WORD *wptr,
		  my_off_t filepos)
{
  uchar buf[HA_FT_MAXBYTELEN+16];
  DBUG_ENTER("_ft_make_key");

#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
  {
    float weight=(float) ((filepos==HA_OFFSET_ERROR) ? 0 : wptr->weight);
    mi_float4store(buf,weight);
  }
#else
#error
#endif

  int2store(buf+HA_FT_WLEN,wptr->len);
  memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len);
  DBUG_RETURN(_mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos));
}
示例#10
0
static void 
create_key(char *key, uint rownr)
{
	if (keyinfo[0].seg[0].null_bit) {
		if (rownr == 0) {
			key[0] = 1;	/* null key */
			key[1] = 0;	/* Fore easy print of key */
			return;
		}
		*key++ = 0;
	}
	if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH)) {
		uint		tmp;
		create_key_part(key + 2, rownr);
		tmp = strlen(key + 2);
		int2store(key, tmp);
	} else
		create_key_part(key, rownr);
}
示例#11
0
/* {{{ mysqlnd_stmt_execute_store_types */
static void
mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p)
{
	unsigned int i;
	for (i = 0; i < stmt->param_count; i++) {
		short current_type = stmt->param_bind[i].type;
		zval *parameter = &stmt->param_bind[i].zv;
		/* our types are not unsigned */
#if SIZEOF_ZEND_LONG==8
		if (current_type == MYSQL_TYPE_LONG) {
			current_type = MYSQL_TYPE_LONGLONG;
		}
#endif
		ZVAL_DEREF(parameter);
		if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
			/*
			  if it doesn't fit in a long send it as a string.
			  Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
			*/
			if (Z_TYPE_P(parameter) != IS_LONG) {
				const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter;
				/*
				  In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type.
				  The actual transformation has been performed several dozens line above.
				*/
				if (Z_TYPE_P(tmp_data) == IS_STRING) {
					current_type = MYSQL_TYPE_VAR_STRING;
					/*
					  don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING
					  we force convert_to_long_ex in all cases, thus the type will be right in the next switch.
					  if the type is however not long, then we will do a goto in the next switch.
					  We want to preserve the original bind type given by the user. Thus, we do these hacks.
					*/
				}
			}
		}
		int2store(*p, current_type);
		*p+= 2;
	}
}
示例#12
0
/* {{{ mysqlnd_command::set_option */
static enum_func_status
MYSQLND_METHOD(mysqlnd_command, set_option)(MYSQLND_CONN_DATA * const conn, const enum_mysqlnd_server_option option)
{
	const func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
	const func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
	zend_uchar buffer[2];
	enum_func_status ret = FAIL;

	DBG_ENTER("mysqlnd_command::set_option");
	int2store(buffer, (unsigned int) option);

	ret = send_command(conn->payload_decoder_factory, COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
					   &conn->state,
					   conn->error_info,
					   conn->upsert_status,
					   conn->stats,
					   conn->m->send_close,
					   conn);
	if (PASS == ret) {
		ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE,
		                                   conn->error_info, conn->upsert_status, &conn->last_message);
	}
	DBG_RETURN(ret);
}
示例#13
0
文件: pack.c 项目: knielsen/mariadb
uchar *net_store_length(uchar *packet, ulonglong length)
{
  if (length < 251)
  {
    *packet= (uchar) length;
    return packet+1;
  }
  /* 251 is reserved for NULL */
  if (length < 65536)
  {
    *packet++=252;
    int2store(packet, (uint) length);
    return packet+2;
  }
  if (length < 16777216)
  {
    *packet++=253;
    int3store(packet, (ulong) length);
    return packet+3;
  }
  *packet++=254;
  int8store(packet,length);
  return packet+8;
}
示例#14
0
static void update_record(uchar *record)
{
  uchar *pos=record+1;
  if (recinfo[1].type == FIELD_BLOB)
  {
    uchar *column,*ptr;
    int length;
    length=uint4korr(pos);			/* Long blob */
    memcpy_fixed(&column,pos+4,sizeof(char*));
    memcpy(blob_key,column,length);		/* Move old key */
    ptr=blob_key;
    memcpy_fixed(pos+4,&ptr,sizeof(char*));	/* Store pointer to new key */
    if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
      default_charset_info->cset->casedn(default_charset_info,
                                         (char*) blob_key, length,
                                         (char*) blob_key, length);
    pos+=recinfo[1].length;
  }
  else if (recinfo[1].type == FIELD_VARCHAR)
  {
    uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
    uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
    default_charset_info->cset->casedn(default_charset_info,
                                       (char*) pos + pack_length, length,
                                       (char*) pos + pack_length, length);
    pos+=recinfo[1].length;
  }
  else
  {
    if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
      default_charset_info->cset->casedn(default_charset_info,
                                         (char*) pos, keyinfo[0].seg[0].length,
                                         (char*) pos, keyinfo[0].seg[0].length);
    pos+=recinfo[1].length;
  }

  if (recinfo[2].type == FIELD_BLOB)
  {
    uchar *column;
    int length;
    length=uint4korr(pos);
    memcpy_fixed(&column,pos+4,sizeof(char*));
    memcpy(blob_record,column,length);
    bfill(blob_record+length,20,'.');	/* Make it larger */
    length+=20;
    int4store(pos,length);
    column= blob_record;
    memcpy_fixed(pos+4,&column,sizeof(char*));
  }
  else if (recinfo[2].type == FIELD_VARCHAR)
  {
    /* Second field is longer than 10 characters */
    uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
    uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
    bfill(pos+pack_length+length,recinfo[2].length-length-pack_length,'.');
    length=recinfo[2].length-pack_length;
    if (pack_length == 1)
      *(uchar*) pos= (uchar) length;
    else
      int2store(pos,length);
  }
  else
  {
    bfill(pos+recinfo[2].length-10,10,'.');
  }
}
示例#15
0
/* {{{ mysqlnd_stmt_execute_store_params */
static enum_func_status
mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p,
								  size_t *buf_len, unsigned int null_byte_offset TSRMLS_DC)
{
	MYSQLND_STMT_DATA * stmt = s->data;
	unsigned int i = 0;
	zend_uchar * provided_buffer = *buf;
	size_t left = (*buf_len - (*p - *buf));
	size_t data_size = 0;
	zval **copies = NULL;/* if there are different types */
	enum_func_status ret = FAIL;
	int resend_types_next_time = 0;

	DBG_ENTER("mysqlnd_stmt_execute_store_params");

/* 1. Store type information */
	/*
	  check if need to send the types even if stmt->send_types_to_server is 0. This is because
	  if we send "i" (42) then the type will be int and the server will expect int. However, if next
	  time we try to send > LONG_MAX, the conversion to string will send a string and the server
	  won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values
	  occur, and force resend for the next execution.
	*/
	for (i = 0; i < stmt->param_count; i++) {
		if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL &&
			(stmt->param_bind[i].type == MYSQL_TYPE_LONG || stmt->param_bind[i].type == MYSQL_TYPE_LONGLONG))
		{
			/* always copy the var, because we do many conversions */
			if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
				PASS != mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
			{
				SET_OOM_ERROR(stmt->error_info);
				goto end;
			}
			/*
			  if it doesn't fit in a long send it as a string.
			  Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
			*/
			if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
				zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
				convert_to_double_ex(&tmp_data);
				if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) {
					stmt->send_types_to_server = resend_types_next_time = 1;
				}
			}
		}
	}

	int1store(*p, stmt->send_types_to_server); 
	(*p)++;

	if (stmt->send_types_to_server) {
		/* 2 bytes per type, and leave 20 bytes for future use */
		if (left < ((stmt->param_count * 2) + 20)) {
			unsigned int offset = *p - *buf;
			zend_uchar *tmp_buf;
			*buf_len = offset + stmt->param_count * 2 + 20;
			tmp_buf = mnd_emalloc(*buf_len);
			if (!tmp_buf) {
				SET_OOM_ERROR(stmt->error_info);
				goto end;
			}
			memcpy(tmp_buf, *buf, offset);
			*buf = tmp_buf;

			/* Update our pos pointer */
			*p = *buf + offset;
		}
		for (i = 0; i < stmt->param_count; i++) {
			short current_type = stmt->param_bind[i].type;
			/* our types are not unsigned */
#if SIZEOF_LONG==8  
			if (current_type == MYSQL_TYPE_LONG) {
				current_type = MYSQL_TYPE_LONGLONG;
			}
#endif
			if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
				/*
				  if it doesn't fit in a long send it as a string.
				  Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
				*/
				if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
					zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;

					convert_to_double_ex(&tmp_data);
					if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) {
						convert_to_string_ex(&tmp_data);
						current_type = MYSQL_TYPE_VAR_STRING;
						/*
						  don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING
						  we force convert_to_long_ex in all cases, thus the type will be right in the next switch.
						  if the type is however not long, then we will do a goto in the next switch.
						  We want to preserve the original bind type given by the user. Thus, we do these hacks.
						*/
					} else {
						convert_to_long_ex(&tmp_data);
					}
				}
			}
			int2store(*p, current_type);
			*p+= 2;
		}
	}
	stmt->send_types_to_server = resend_types_next_time;

/* 2. Store data */
	/* 2.1 Calculate how much space we need */
	for (i = 0; i < stmt->param_count; i++) {
		unsigned int j;
		zval *the_var = stmt->param_bind[i].zv;

		if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
			continue;
		}
		for (j = i + 1; j < stmt->param_count; j++) {
			if (stmt->param_bind[j].zv == the_var) {
				/* Double binding of the same zval, make a copy */
				if (!copies || !copies[i]) {
					if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
						SET_OOM_ERROR(stmt->error_info);
						goto end;
					}
				}
				break; 
			}
		}

		switch (stmt->param_bind[i].type) {
			case MYSQL_TYPE_DOUBLE:
				data_size += 8;
				if (Z_TYPE_P(the_var) != IS_DOUBLE) {
					if (!copies || !copies[i]) {
						if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
							SET_OOM_ERROR(stmt->error_info);
							goto end;
						}
					}
				}
				break;
			case MYSQL_TYPE_LONGLONG:
				{
					zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
					if (Z_TYPE_P(tmp_data) == IS_STRING) {
						goto use_string;
					}
					convert_to_long_ex(&tmp_data);
				}
				data_size += 8;
				break;
			case MYSQL_TYPE_LONG:
				{
					zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
					if (Z_TYPE_P(tmp_data) == IS_STRING) {
						goto use_string;
					}
					convert_to_long_ex(&tmp_data);
				}
				data_size += 4;
				break;
			case MYSQL_TYPE_LONG_BLOB:
				if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
					/*
					  User hasn't sent anything, we will send empty string.
					  Empty string has length of 0, encoded in 1 byte. No real
					  data will follows after it.
					*/
					data_size++;
				}
				break;
			case MYSQL_TYPE_VAR_STRING:
use_string:
				data_size += 8; /* max 8 bytes for size */
#if MYSQLND_UNICODE
				if (Z_TYPE_P(the_var) != IS_STRING || Z_TYPE_P(the_var) == IS_UNICODE)
#else
				if (Z_TYPE_P(the_var) != IS_STRING)
#endif
				{
					if (!copies || !copies[i]) {
						if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
							SET_OOM_ERROR(stmt->error_info);
							goto end;
						}
					}
					the_var = copies[i];
#if MYSQLND_UNICODE
					if (Z_TYPE_P(the_var) == IS_UNICODE) {
						zval_unicode_to_string_ex(the_var, UG(utf8_conv) TSRMLS_CC);
					}
#endif
				}
				convert_to_string_ex(&the_var);
				data_size += Z_STRLEN_P(the_var);
				break;
		}
	}

	/* 2.2 Enlarge the buffer, if needed */
	left = (*buf_len - (*p - *buf));
	if (left < data_size) {
		unsigned int offset = *p - *buf;
		zend_uchar *tmp_buf;
		*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
		tmp_buf = mnd_emalloc(*buf_len);
		if (!tmp_buf) {
			SET_OOM_ERROR(stmt->error_info);
			goto end;
		}
		memcpy(tmp_buf, *buf, offset);
		/*
		  When too many columns the buffer provided to the function might not be sufficient.
		  In this case new buffer has been allocated above. When we allocate a buffer and then
		  allocate a bigger one here, we should free the first one.
		*/
		if (*buf != provided_buffer) {
			mnd_efree(*buf);
		}
		*buf = tmp_buf;
		/* Update our pos pointer */
		*p = *buf + offset;
	}

	/* 2.3 Store the actual data */
	for (i = 0; i < stmt->param_count; i++) {
		zval *data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
		/* Handle long data */
		if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
			(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
		} else {
			switch (stmt->param_bind[i].type) {
				case MYSQL_TYPE_DOUBLE:
					convert_to_double_ex(&data);
					float8store(*p, Z_DVAL_P(data));
					(*p) += 8;
					break;
				case MYSQL_TYPE_LONGLONG:
					if (Z_TYPE_P(data) == IS_STRING) {
						goto send_string;
					}
					/* data has alreade been converted to long */
					int8store(*p, Z_LVAL_P(data));
					(*p) += 8;
					break;
				case MYSQL_TYPE_LONG:
					if (Z_TYPE_P(data) == IS_STRING) {
						goto send_string;
					}
					/* data has alreade been converted to long */
					int4store(*p, Z_LVAL_P(data));
					(*p) += 4;
					break;
				case MYSQL_TYPE_LONG_BLOB:
					if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
						stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
					} else {
						/* send_long_data() not called, send empty string */
						*p = php_mysqlnd_net_store_length(*p, 0);
					}
					break;
				case MYSQL_TYPE_VAR_STRING:
send_string:
					{
						unsigned int len = Z_STRLEN_P(data);
						/* to is after p. The latter hasn't been moved */
						*p = php_mysqlnd_net_store_length(*p, len);
						memcpy(*p, Z_STRVAL_P(data), len);
						(*p) += len;
					}
					break;
				default:
					/* Won't happen, but set to NULL */
					(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
					break;
			}
		}
	}
	ret = PASS;
end:
	if (copies) {
		for (i = 0; i < stmt->param_count; i++) {
			if (copies[i]) {
				zval_ptr_dtor(&copies[i]);
			}
		}
		mnd_efree(copies);
	}

	DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"******");
	DBG_RETURN(ret);
}
示例#16
0
/* {{{ mysqlnd_stmt_execute_store_params */
static void
mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p,
								  size_t *buf_len, unsigned int null_byte_offset TSRMLS_DC)
{
	MYSQLND_STMT_DATA * stmt = s->data;
	unsigned int i = 0;
	size_t left = (*buf_len - (*p - *buf));
	size_t data_size = 0;
	zval **copies = NULL;/* if there are different types */

/* 1. Store type information */
	if (stmt->send_types_to_server) {

		/* 2 bytes per type, and leave 20 bytes for future use */
		if (left < ((stmt->param_count * 2) + 20)) {
			unsigned int offset = *p - *buf;
			zend_uchar *tmp_buf;
			*buf_len = offset + stmt->param_count * 2 + 20;
			tmp_buf = mnd_emalloc(*buf_len);
			memcpy(tmp_buf, *buf, offset);
			*buf = tmp_buf;
			
			/* Update our pos pointer */
			*p = *buf + offset;
		}
		for (i = 0; i < stmt->param_count; i++) {
			/* our types are not unsigned */
#if SIZEOF_LONG==8  
			if (stmt->param_bind[i].type == MYSQL_TYPE_LONG) {
				stmt->param_bind[i].type = MYSQL_TYPE_LONGLONG;
			}
#endif
			int2store(*p, stmt->param_bind[i].type);
			*p+= 2;
		}
	}

/* 2. Store data */
	/* 2.1 Calculate how much space we need */
	for (i = 0; i < stmt->param_count; i++) {
		unsigned int j;
		zval *the_var = stmt->param_bind[i].zv;

		if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB &&
						 Z_TYPE_P(the_var) == IS_NULL)) {
			continue;
		}
		for (j = i + 1; j < stmt->param_count; j++) {
			if (stmt->param_bind[j].zv == the_var) {
				/* Double binding of the same zval, make a copy */
				mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
				break; 
			}
		}

		switch (stmt->param_bind[i].type) {
			case MYSQL_TYPE_DOUBLE:
				data_size += 8;
				if (Z_TYPE_P(the_var) != IS_DOUBLE) {
					if (!copies || !copies[i]) {
						mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
					}
				}
				break;
#if SIZEOF_LONG==8  
			case MYSQL_TYPE_LONGLONG:
				data_size += 8;
#elif SIZEOF_LONG==4
			case MYSQL_TYPE_LONG:
				data_size += 4;
#else
#error "Should not happen"
#endif
				if (Z_TYPE_P(the_var) != IS_LONG) {
					if (!copies || !copies[i]) {
						mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
					}
				}
				break;
			case MYSQL_TYPE_LONG_BLOB:
				if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
					/*
					  User hasn't sent anything, we will send empty string.
					  Empty string has length of 0, encoded in 1 byte. No real
					  data will follows after it.
					*/
					data_size++;
				}
				break;
			case MYSQL_TYPE_VAR_STRING:
				data_size += 8; /* max 8 bytes for size */
#if PHP_MAJOR_VERSION < 6
				if (Z_TYPE_P(the_var) != IS_STRING)
#elif PHP_MAJOR_VERSION >= 6
				if (Z_TYPE_P(the_var) != IS_STRING || Z_TYPE_P(the_var) == IS_UNICODE)
#endif
				{
					if (!copies || !copies[i]) {
						mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
					}
					the_var = copies[i];
#if PHP_MAJOR_VERSION >= 6
					if (Z_TYPE_P(the_var) == IS_UNICODE) {
						zval_unicode_to_string_ex(the_var, UG(utf8_conv) TSRMLS_CC);
					}
#endif
				}
				convert_to_string_ex(&the_var);
				data_size += Z_STRLEN_P(the_var);
				break;
		}

	}

	/* 2.2 Enlarge the buffer, if needed */
	left = (*buf_len - (*p - *buf));
	if (left < data_size) {
		unsigned int offset = *p - *buf;
		zend_uchar *tmp_buf;
		*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
		tmp_buf = mnd_emalloc(*buf_len);
		memcpy(tmp_buf, *buf, offset);
		*buf = tmp_buf;
		/* Update our pos pointer */
		*p = *buf + offset;	
	}

	/* 2.3 Store the actual data */
	for (i = 0; i < stmt->param_count; i++) {
		zval *data = copies && copies[i]? copies[i]: stmt->param_bind[i].zv;
		/* Handle long data */
		if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
			(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
		} else {
			switch (stmt->param_bind[i].type) {
				case MYSQL_TYPE_DOUBLE:
					convert_to_double_ex(&data);
					float8store(*p, Z_DVAL_P(data));
					(*p) += 8;
					break;
#if SIZEOF_LONG==8  
				case MYSQL_TYPE_LONGLONG:
					convert_to_long_ex(&data);
					int8store(*p, Z_LVAL_P(data));
					(*p) += 8;
					break;
#elif SIZEOF_LONG==4
				case MYSQL_TYPE_LONG:
					convert_to_long_ex(&data);
					int4store(*p, Z_LVAL_P(data));
					(*p) += 4;
					break;
#else
#error "Should not happen"
#endif
				case MYSQL_TYPE_LONG_BLOB:
					if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
						stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
					} else {
						/* send_long_data() not called, send empty string */
						*p = php_mysqlnd_net_store_length(*p, 0);
					}
					break;
				case MYSQL_TYPE_VAR_STRING:{
						unsigned int len = Z_STRLEN_P(data);
						/* to is after p. The latter hasn't been moved */
						*p = php_mysqlnd_net_store_length(*p, len);
						memcpy(*p, Z_STRVAL_P(data), len);
						(*p) += len;
					}
					break;
				default:
					/* Won't happen, but set to NULL */
					(*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
					break;
			}
		}
	}
	if (copies) {
		for (i = 0; i < stmt->param_count; i++) {
			if (copies[i]) {
				zval_ptr_dtor(&copies[i]);
			}
		}
		mnd_efree(copies);	
	}
}
示例#17
0
文件: create.c 项目: OPSF/uClinux
int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
		 N_RECINFO *recinfo,
		 ulong records,ulong reloc, uint flags,uint old_options,
		 ulong data_file_length)
{
  register uint i,j;
  File dfile,file;
  int errpos,save_errno;
  uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length,
       key_length,info_length,key_segs,options,min_key_length_skipp,max_block,
       base_pos;
  char buff[max(FN_REFLEN,512)];
  ulong tot_length,pack_reclength;
  enum en_fieldtype type;
  ISAM_SHARE share;
  N_KEYDEF *keydef;
  N_KEYSEG *keyseg;
  N_RECINFO *rec;
  DBUG_ENTER("nisam_create");

  LINT_INIT(dfile);
  pthread_mutex_lock(&THR_LOCK_isam);
  errpos=0;
  options=0;
  base_pos=512;					/* Enough for N_STATE_INFO */
  bzero((byte*) &share,sizeof(share));
  if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
       O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
    goto err;
  errpos=1;
  VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
  if (!(flags & HA_DONT_TOUCH_DATA))
  {
    if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
      goto err;
    errpos=2;
  }
  else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
    options=old_options & (HA_OPTION_COMPRESS_RECORD |
			   HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD);
  if (reloc > records)
    reloc=records;				/* Check if wrong parameter */

	/* Start by checking fields and field-types used */
  reclength=0;
  for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L;
       rec->base.type != (int) FIELD_LAST;
       rec++,fields++)
  {
    reclength+=rec->base.length;
    if ((type=(enum en_fieldtype) rec->base.type))
    {
      packed++;
      if (type == FIELD_BLOB)
      {
	share.base.blobs++;
	rec->base.length-= sizeof(char*);	/* Don't calc pointer */
	if (pack_reclength != NI_POS_ERROR)
	{
	  if (rec->base.length == 4)
	    pack_reclength= (ulong) NI_POS_ERROR;
	  else
	    pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
	}
      }
      else if (type == FIELD_SKIP_PRESPACE ||
	       type == FIELD_SKIP_ENDSPACE)
      {
	if (pack_reclength != NI_POS_ERROR)
	  pack_reclength+= rec->base.length > 255 ? 2 : 1;
	min_pack_length++;
      }
      else if (type == FIELD_ZERO)
	packed--;
      else if (type != FIELD_SKIP_ZERO)
      {
	min_pack_length+=rec->base.length;
	packed--;				/* Not a pack record type */
      }
    }
    else
      min_pack_length+=rec->base.length;
  }
  if ((packed & 7) == 1)
  {				/* Bad packing, try to remove a zero-field */
    while (rec != recinfo)
    {
      rec--;
      if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1)
      {
	rec->base.type=(int) FIELD_NORMAL;
	packed--;
	min_pack_length++;
	break;
      }
    }
  }
  if (packed && !(options & HA_OPTION_COMPRESS_RECORD))
    options|=HA_OPTION_PACK_RECORD;	/* Must use packed records */

  packed=(packed+7)/8;
  if (pack_reclength != NI_POS_ERROR)
    pack_reclength+= reclength+packed;
  min_pack_length+=packed;

  if (options & HA_OPTION_COMPRESS_RECORD)
  {
    if (data_file_length >= (1L << 24))
      pointer=4;
    else if (data_file_length >= (1L << 16))
      pointer=3;
    else
      pointer=2;
  }
  else if (((records == 0L && pack_reclength < 255) ||
	    options & HA_OPTION_PACK_RECORD) ||
	   records >= (ulong) 16000000L ||
	   pack_reclength == (ulong) NI_POS_ERROR ||
	   ((options & HA_OPTION_PACK_RECORD) &&
	    pack_reclength+4 >= (ulong) 14000000L/records))
    pointer=4;
  else if (records == 0L || records >= (ulong) 65000L ||
	   ((options & HA_OPTION_PACK_RECORD) &&
	    pack_reclength+4 >= (ulong) 60000L/records))
    pointer=3;
  else
    pointer=2;

  max_block=max_key_length=0; tot_length=key_segs=0;
  for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++)
  {
    share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR;
    share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L;
    min_key_length_skipp=length=0;
    key_length=pointer;

    if (keydef->base.flag & HA_PACK_KEY &&
	keydef->seg[0].base.length > 127)
      keydef->base.flag&= ~HA_PACK_KEY;		/* Can't pack long keys */
    if (keydef->base.flag & HA_PACK_KEY)
    {
      if ((keydef->seg[0].base.flag & HA_SPACE_PACK) &&
	  keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM)
	keydef->seg[0].base.flag&= ~HA_SPACE_PACK;
      if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
	length++;
      keydef->seg[0].base.flag|=HA_PACK_KEY;	/* for easyer intern test */
      options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
      if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
	min_key_length_skipp+=keydef->seg[0].base.length;
    }
    keydef->base.keysegs=0;
    for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++)
    {
      keydef->base.keysegs++;
      if (keyseg->base.length > 127)
	keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY);
      if (keyseg->base.flag & HA_SPACE_PACK)
      {
	keydef->base.flag |= HA_SPACE_PACK_USED;
	options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
	length++;
	min_key_length_skipp+=keyseg->base.length;
      }
      key_length+= keyseg->base.length;
    }
    bzero((gptr) keyseg,sizeof(keyseg[0]));
    keyseg->base.length=(uint16) pointer;	/* Last key part is pointer */
    key_segs+=keydef->base.keysegs;
    length+=key_length;
    keydef->base.block_length=nisam_block_size;
    keydef->base.keylength= (uint16) key_length;
    keydef->base.minlength= (uint16) (length-min_key_length_skipp);
    keydef->base.maxlength= (uint16) length;

    if ((uint) keydef->base.block_length > max_block)
      max_block=(uint) keydef->base.block_length;
    if (length > max_key_length)
      max_key_length= length;
    tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/
				   (length*2)))*
      (ulong) keydef->base.block_length;
  }
  info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+
		      (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+
		      fields*sizeof(N_SAVE_RECINFO));

  bmove(share.state.header.file_version,(byte*) nisam_file_magic,4);
  old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
			HA_OPTION_COMPRESS_RECORD |
			HA_OPTION_TEMP_COMPRESS_RECORD: 0);
  int2store(share.state.header.options,old_options);
  int2store(share.state.header.header_length,info_length);
  int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO));
  int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO));
  int2store(share.state.header.base_pos,base_pos);

  share.state.dellink = NI_POS_ERROR;
  share.state.process=	(ulong) getpid();
  share.state.uniq=	(ulong) file;
  share.state.loop=	0;
  share.state.version=	(ulong) time((time_t*) 0);
  share.base.options=options;
  share.base.rec_reflength=pointer;
  share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 :
			   tot_length > 120000L ? 2 : 1);
  share.base.keys= share.state.keys = keys;
  share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length,
							  nisam_block_size);
  share.base.max_block=max_block;
  share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4);
  share.base.records=records;
  share.base.reloc=reloc;
  share.base.reclength=reclength;
  share.base.pack_reclength=
    (uint) (reclength+packed-share.base.blobs*sizeof(char*));
  share.base.max_pack_length=pack_reclength;
  share.base.min_pack_length=min_pack_length;
  share.base.pack_bits=packed;
  share.base.fields=fields;
  share.base.pack_fields=packed;
  share.base.sortkey= (ushort) ~0;
  share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L :
    (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
    (ulong) (1L << (pointer*8)) :
    (pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR :
    ((ulong) reclength * (1L << (pointer*8)));
  share.base.max_key_file_length= (share.base.key_reflength == 3 ?
				   NI_POS_ERROR :
				   (ulong)
				   (1L << (share.base.key_reflength*8))*512);
  share.base.min_block_length=
    (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH &&
     ! share.base.blobs) ?
    max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) :
    N_EXTEND_BLOCK_LENGTH;
  if (! (flags & HA_DONT_TOUCH_DATA))
    share.base.create_time= (long) time((time_t*) 0);

  bzero(buff,base_pos);
  if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
      my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
      my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP)))
    goto err;

  for (i=0 ; i < share.base.keys ; i++)
  {
    if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF),
		 MYF(MY_NABP)))
      goto err;
    for (j=0 ; j <= keyinfo[i].base.keysegs ; j++)
    {
      if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG),
		   MYF(MY_NABP)))
	goto err;
    }
  }
  for (i=0 ; i < share.base.fields ; i++)
    if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO),
		 MYF(MY_NABP)))
      goto err;

	/* Enlarge files */
  if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
    goto err;

  if (! (flags & HA_DONT_TOUCH_DATA))
  {
#ifdef USE_RELOC
    if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0)))
      goto err;
#endif
    errpos=1;
    if (my_close(dfile,MYF(0)))
      goto err;
  }
  errpos=0;
  pthread_mutex_unlock(&THR_LOCK_isam);
  if (my_close(file,MYF(0)))
    goto err;
  DBUG_RETURN(0);

err:
  pthread_mutex_unlock(&THR_LOCK_isam);
  save_errno=my_errno;
  switch (errpos) {
  case 2:
    VOID(my_close(dfile,MYF(0)));
    /* fall through */
  case 1:
    VOID(my_close(file,MYF(0)));
  }
  my_errno=save_errno;				/* R{tt felkod tillbaka */
  DBUG_RETURN(-1);
} /* nisam_create */
示例#18
0
static int send_client_reply_packet(MCPVIO_EXT *mpvio,
                                    const uchar *data, int data_len)
{
    MYSQL *mysql= mpvio->mysql;
    NET *net= &mysql->net;
    char *buff, *end;
    size_t conn_attr_len= (mysql->options.extension) ?
                          mysql->options.extension->connect_attrs_len : 0;

    /* see end= buff+32 below, fixed size of the packet is 32 bytes */
    buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);

    mysql->client_flag|= mysql->options.client_flag;
    mysql->client_flag|= CLIENT_CAPABILITIES;

    if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
        mysql->client_flag|= CLIENT_MULTI_RESULTS;

#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
    if (mysql->options.ssl_key || mysql->options.ssl_cert ||
            mysql->options.ssl_ca || mysql->options.ssl_capath ||
            mysql->options.ssl_cipher)
        mysql->options.use_ssl= 1;
    if (mysql->options.use_ssl)
        mysql->client_flag|= CLIENT_SSL;

    /* if server doesn't support SSL and verification of server certificate
       was set to mandatory, we need to return an error */
    if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
    {
        if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ||
                (mysql->options.extension && (mysql->options.extension->ssl_fp ||
                                              mysql->options.extension->ssl_fp_list)))
        {
            my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
                         ER(CR_SSL_CONNECTION_ERROR),
                         "Server doesn't support SSL");
            goto error;
        }
    }

#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
    if (mpvio->db)
        mysql->client_flag|= CLIENT_CONNECT_WITH_DB;

    /* Remove options that server doesn't support */
    mysql->client_flag= mysql->client_flag &
                        (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
                         | mysql->server_capabilities);

#ifndef HAVE_COMPRESS
    mysql->client_flag&= ~CLIENT_COMPRESS;
#endif

    if (mysql->client_flag & CLIENT_PROTOCOL_41)
    {
        /* 4.1 server and 4.1 client has a 32 byte option flag */
        int4store(buff,mysql->client_flag);
        int4store(buff+4, net->max_packet_size);
        buff[8]= (char) mysql->charset->nr;
        bzero(buff+9, 32-9);
        end= buff+32;
    }
    else
    {
        int2store(buff, mysql->client_flag);
        int3store(buff+2, net->max_packet_size);
        end= buff+5;
    }
#ifdef HAVE_OPENSSL
    if (mysql->options.ssl_key ||
            mysql->options.ssl_cert ||
            mysql->options.ssl_ca ||
            mysql->options.ssl_capath ||
            mysql->options.ssl_cipher
#ifdef CRL_IMPLEMENTED
            || (mysql->options.extension &&
                (mysql->options.extension->ssl_crl ||
                 mysql->options.extension->ssl_crlpath))
#endif
       )
        mysql->options.use_ssl= 1;

    if (mysql->options.use_ssl &&
            (mysql->client_flag & CLIENT_SSL))
    {
        SSL *ssl;
        /*
          Send mysql->client_flag, max_packet_size - unencrypted otherwise
          the server does not know we want to do SSL
        */
        if (my_net_write(net, (char*)buff, (size_t) (end-buff)) || net_flush(net))
        {
            my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                         ER(CR_SERVER_LOST_EXTENDED),
                         "sending connection information to server",
                         errno);
            goto error;
        }

        /* Create SSL */
        if (!(ssl= my_ssl_init(mysql)))
            goto error;

        /* Connect to the server */
        if (my_ssl_connect(ssl))
        {
            SSL_free(ssl);
            goto error;
        }

        if (mysql->options.extension &&
                (mysql->options.extension->ssl_fp || mysql->options.extension->ssl_fp_list))
        {
            if (ma_ssl_verify_fingerprint(ssl))
                goto error;
        }

        if ((mysql->options.ssl_ca || mysql->options.ssl_capath) &&
                (mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
                my_ssl_verify_server_cert(ssl))
            goto error;
    }
#endif /* HAVE_OPENSSL */

    DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
                       mysql->server_version, mysql->server_capabilities,
                       mysql->server_status, mysql->client_flag));

    compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);

    /* This needs to be changed as it's not useful with big packets */
    if (mysql->user[0])
        strmake(end, mysql->user, USERNAME_LENGTH);
    else
        read_user_name(end);

    /* We have to handle different version of handshake here */
    DBUG_PRINT("info",("user: %s",end));
    end= strend(end) + 1;
    if (data_len)
    {
        if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
        {
            *end++= data_len;
            memcpy(end, data, data_len);
            end+= data_len;
        }
        else
        {
            DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
            memcpy(end, data, data_len);
            end+= data_len;
        }
    }
    else
        *end++= 0;

    /* Add database if needed */
    if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
    {
        end= strmake(end, mpvio->db, NAME_LEN) + 1;
        mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
    }

    if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
        end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;

    end= ma_send_connect_attr(mysql, end);

    /* Write authentication package */
    if (my_net_write(net, buff, (size_t) (end-buff)) || net_flush(net))
    {
        my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                     ER(CR_SERVER_LOST_EXTENDED),
                     "sending authentication information",
                     errno);
        goto error;
    }
    my_afree(buff);
    return 0;

error:
    my_afree(buff);
    return 1;
}
示例#19
0
static int create_sys_files(struct languages *lang_head,
			    struct errors *error_head, uint row_count)
{
  FILE *to;
  uint csnum= 0, length, i, row_nr;
  uchar head[32];
  char outfile[FN_REFLEN], *outfile_end;
  long start_pos;
  struct message *tmp;
  struct languages *tmp_lang;
  struct errors *tmp_error;

  MY_STAT stat_info;
  DBUG_ENTER("create_sys_files");

  /*
     going over all languages and assembling corresponding error messages
  */
  for (tmp_lang= lang_head; tmp_lang; tmp_lang= tmp_lang->next_lang)
  {

    /* setting charset name */
    if (!(csnum= get_charset_number(tmp_lang->charset, MY_CS_PRIMARY)))
    {
      fprintf(stderr, "Unknown charset '%s' in '%s'\n", tmp_lang->charset,
	      TXTFILE);
      DBUG_RETURN(1);
    }

    outfile_end= strxmov(outfile, DATADIRECTORY, 
                         tmp_lang->lang_long_name, NullS);
    if (!my_stat(outfile, &stat_info,MYF(0)))
    {
      if (my_mkdir(outfile, 0777,MYF(0)) < 0)
      {
        fprintf(stderr, "Can't create output directory for %s\n", 
                outfile);
        DBUG_RETURN(1);
      }
    }

    strxmov(outfile_end, FN_ROOTDIR, OUTFILE, NullS);

    if (!(to= my_fopen(outfile, O_WRONLY | FILE_BINARY, MYF(MY_WME))))
      DBUG_RETURN(1);

    /* 2 is for 2 bytes to store row position / error message */
    start_pos= (long) (HEADER_LENGTH + row_count * 2);
    fseek(to, start_pos, 0);
    row_nr= 0;
    for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
    {
      /* dealing with messages */
      tmp= find_message(tmp_error, tmp_lang->lang_short_name, FALSE);

      if (!tmp)
      {
	fprintf(stderr,
		"Did not find message for %s neither in %s nor in default "
		"language\n", tmp_error->er_name, tmp_lang->lang_short_name);
	goto err;
      }
      if (copy_rows(to, tmp->text, row_nr, start_pos))
      {
	fprintf(stderr, "Failed to copy rows to %s\n", outfile);
	goto err;
      }
      row_nr++;
    }

    /* continue with header of the errmsg.sys file */
    length= ftell(to) - HEADER_LENGTH - row_count * 2;
    bzero((uchar*) head, HEADER_LENGTH);
    bmove((uchar *) head, (uchar *) file_head, 4);
    head[4]= 1;
    int2store(head + 6, length);
    int2store(head + 8, row_count);
    head[30]= csnum;

    my_fseek(to, 0l, MY_SEEK_SET, MYF(0));
    if (my_fwrite(to, (uchar*) head, HEADER_LENGTH, MYF(MY_WME | MY_FNABP)))
      goto err;

    for (i= 0; i < row_count; i++)
    {
      int2store(head, file_pos[i]);
      if (my_fwrite(to, (uchar*) head, 2, MYF(MY_WME | MY_FNABP)))
	goto err;
    }
    my_fclose(to, MYF(0));
  }
  DBUG_RETURN(0);

err:
  my_fclose(to, MYF(0));
  DBUG_RETURN(1);
}
示例#20
0
static void create_record(uchar *record,uint rownr)
{
  uchar *pos;
  bzero((char*) record,MAX_REC_LENGTH);
  record[0]=1;					/* delete marker */
  if (rownr == 0 && keyinfo[0].seg[0].null_bit)
    record[0]|=keyinfo[0].seg[0].null_bit;	/* Null key */

  pos=record+1;
  if (recinfo[1].type == FIELD_BLOB)
  {
    uint tmp;
    uchar *ptr;
    create_key_part(blob_key,rownr);
    tmp=strlen((char*) blob_key);
    int4store(pos,tmp);
    ptr=blob_key;
    memcpy(pos+4, &ptr, sizeof(char*));
    pos+=recinfo[1].length;
  }
  else if (recinfo[1].type == FIELD_VARCHAR)
  {
    uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
    create_key_part(pos+pack_length,rownr);
    tmp= strlen((char*) pos+pack_length);
    if (pack_length == 1)
      *(uchar*) pos= (uchar) tmp;
    else
      int2store(pos,tmp);
    pos+= recinfo[1].length;
  }
  else
  {
    create_key_part(pos,rownr);
    pos+=recinfo[1].length;
  }
  if (recinfo[2].type == FIELD_BLOB)
  {
    uint tmp;
    uchar *ptr;;
    sprintf((char*) blob_record,"... row: %d", rownr);
    strappend((char*) blob_record,MY_MAX(MAX_REC_LENGTH-rownr,10),' ');
    tmp=strlen((char*) blob_record);
    int4store(pos,tmp);
    ptr=blob_record;
    memcpy(pos+4, &ptr, sizeof(char*));
  }
  else if (recinfo[2].type == FIELD_VARCHAR)
  {
    uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
    sprintf((char*) pos+pack_length, "... row: %d", rownr);
    tmp= strlen((char*) pos+pack_length);
    if (pack_length == 1)
      *pos= (uchar) tmp;
    else
      int2store(pos,tmp);
  }
  else
  {
    sprintf((char*) pos,"... row: %d", rownr);
    strappend((char*) pos,recinfo[2].length,' ');
  }
}