Exemplo n.º 1
0
size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags)
{
  size_t writtenbytes =0;
  my_off_t seekptr;
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
  uint errors;
#endif
  DBUG_ENTER("my_fwrite");
  DBUG_PRINT("my",("stream: 0x%lx  Buffer: 0x%lx  Count: %u  MyFlags: %d",
		   (long) stream, (long) Buffer, (uint) Count, MyFlags));

#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
  errors=0;
#endif
  seekptr= ftell(stream);
  for (;;)
  {
    size_t written;
    if ((written = (size_t) fwrite((char*) Buffer,sizeof(char),
                                   Count, stream)) != Count)
    {
      DBUG_PRINT("error",("Write only %d bytes", (int) writtenbytes));
      my_errno=errno;
      if (written != (size_t) -1)
      {
	seekptr+=written;
	Buffer+=written;
	writtenbytes+=written;
	Count-=written;
      }
#ifdef EINTR
      if (errno == EINTR)
      {
	(void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0));
	continue;
      }
#endif
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
      if (my_thread_var->abort)
	MyFlags&= ~ MY_WAIT_IF_FULL;		/* End if aborted by user */

      if ((errno == ENOSPC || errno == EDQUOT) &&
          (MyFlags & MY_WAIT_IF_FULL))
      {
        wait_for_free_space("[stream]", errors);
        errors++;
        (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0));
        continue;
      }
#endif
      if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP)))
      {
	if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
	{
	  my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
		   my_filename(my_fileno(stream)),errno);
	}
	writtenbytes= (size_t) -1;        /* Return that we got error */
	break;
      }
    }
    if (MyFlags & (MY_NABP | MY_FNABP))
      writtenbytes= 0;				/* Everything OK */
    else
      writtenbytes+= written;
    break;
  }
  DBUG_RETURN(writtenbytes);
} /* my_fwrite */
Exemplo n.º 2
0
MY_DIR	*my_dir(const char *path, myf MyFlags)
{
  char          *buffer;
  MY_DIR        *result= 0;
  FILEINFO      finfo;
  DYNAMIC_ARRAY *dir_entries_storage;
  MEM_ROOT      *names_storage;
  DIR		*dirp;
  struct dirent *dp;
  char		tmp_path[FN_REFLEN + 2], *tmp_file;
  char	dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];

  DBUG_ENTER("my_dir");
  DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));

#if !defined(HAVE_READDIR_R)
  mysql_mutex_lock(&THR_LOCK_open);
#endif

  dirp = opendir(directory_file_name(tmp_path,(char *) path));
#if defined(__amiga__)
  if ((dirp->dd_fd) < 0)			/* Directory doesn't exists */
    goto error;
#endif
  if (dirp == NULL || 
      ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
                           ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
                           sizeof(MEM_ROOT), MyFlags)))
    goto error;

  dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); 
  names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
                             ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
  
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
  {
    my_free(buffer);
    goto error;
  }
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
  
  /* MY_DIR structure is allocated and completly initialized at this point */
  result= (MY_DIR*)buffer;

  tmp_file=strend(tmp_path);

  dp= (struct dirent*) dirent_tmp;
  
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
  {
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
      goto error;
    
    if (MyFlags & MY_WANT_STAT)
    {
      if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, 
                                               sizeof(MY_STAT))))
        goto error;
      
      memset(finfo.mystat, 0, sizeof(MY_STAT));
      (void) strmov(tmp_file,dp->d_name);
      (void) my_stat(tmp_path, finfo.mystat, MyFlags);
      if (!(finfo.mystat->st_mode & MY_S_IREAD))
        continue;
    }
    else
      finfo.mystat= NULL;

    if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
      goto error;
  }

  (void) closedir(dirp);
#if !defined(HAVE_READDIR_R)
  mysql_mutex_unlock(&THR_LOCK_open);
#endif
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
  result->number_off_files= dir_entries_storage->elements;
  
  if (!(MyFlags & MY_DONT_SORT))
    my_qsort((void *) result->dir_entry, result->number_off_files,
          sizeof(FILEINFO), (qsort_cmp) comp_names);
  DBUG_RETURN(result);

 error:
#if !defined(HAVE_READDIR_R)
  mysql_mutex_unlock(&THR_LOCK_open);
#endif
  my_errno=errno;
  if (dirp)
    (void) closedir(dirp);
  my_dirend(result);
  if (MyFlags & (MY_FAE | MY_WME))
  {
    char errbuf[MYSYS_STRERROR_SIZE];
    my_error(EE_DIR, MYF(ME_BELL+ME_WAITTANG), path,
             my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
  }
  DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
Exemplo n.º 3
0
int mrn_add_index_param(MRN_SHARE *share, KEY *key_info, int i)
{
  int error;
  char *param_string = NULL;
#if MYSQL_VERSION_ID >= 50500
  int title_length;
  char *sprit_ptr[2];
  char *tmp_ptr, *start_ptr;
#endif
  THD *thd = current_thd;
  MRN_DBUG_ENTER_FUNCTION();

#if MYSQL_VERSION_ID >= 50500
  if (key_info->comment.length == 0)
  {
    if (share->key_tokenizer[i]) {
      my_free(share->key_tokenizer[i]);
    }
    share->key_tokenizer[i] = mrn_my_strdup(mrn_default_tokenizer, MYF(MY_WME));
    if (!share->key_tokenizer[i]) {
      error = HA_ERR_OUT_OF_MEM;
      goto error;
    }
    share->key_tokenizer_length[i] = strlen(share->key_tokenizer[i]);

    DBUG_RETURN(0);
  }
  DBUG_PRINT("info", ("mroonga create comment string"));
  if (
    !(param_string = mrn_my_strndup(key_info->comment.str,
                                    key_info->comment.length,
                                    MYF(MY_WME)))
  ) {
    error = HA_ERR_OUT_OF_MEM;
    goto error_alloc_param_string;
  }
  DBUG_PRINT("info", ("mroonga comment string=%s", param_string));

  sprit_ptr[0] = param_string;
  while (sprit_ptr[0])
  {
    if ((sprit_ptr[1] = strchr(sprit_ptr[0], ',')))
    {
      *sprit_ptr[1] = '\0';
      sprit_ptr[1]++;
    }
    tmp_ptr = sprit_ptr[0];
    sprit_ptr[0] = sprit_ptr[1];
    while (*tmp_ptr == ' ' || *tmp_ptr == '\r' ||
      *tmp_ptr == '\n' || *tmp_ptr == '\t')
      tmp_ptr++;

    if (*tmp_ptr == '\0')
      continue;

    title_length = 0;
    start_ptr = tmp_ptr;
    while (*start_ptr != ' ' && *start_ptr != '\'' &&
      *start_ptr != '"' && *start_ptr != '\0' &&
      *start_ptr != '\r' && *start_ptr != '\n' &&
      *start_ptr != '\t')
    {
      title_length++;
      start_ptr++;
    }

    switch (title_length)
    {
      case 5:
        MRN_PARAM_STR_LIST("table", index_table, i);
        break;
      case 6:
        push_warning_printf(thd, MRN_SEVERITY_WARNING,
                            ER_WARN_DEPRECATED_SYNTAX,
                            ER(ER_WARN_DEPRECATED_SYNTAX),
                            "parser", "tokenizer");
        MRN_PARAM_STR_LIST("parser", key_tokenizer, i);
        break;
      case 9:
        MRN_PARAM_STR_LIST("tokenizer", key_tokenizer, i);
        break;
      default:
        break;
    }
  }
#endif
  if (!share->key_tokenizer[i]) {
    share->key_tokenizer[i] = mrn_my_strdup(mrn_default_tokenizer, MYF(MY_WME));
    if (!share->key_tokenizer[i]) {
      error = HA_ERR_OUT_OF_MEM;
      goto error;
    }
    share->key_tokenizer_length[i] = strlen(share->key_tokenizer[i]);
  }

  if (param_string)
    my_free(param_string);
  DBUG_RETURN(0);

error:
  if (param_string)
    my_free(param_string);
#if MYSQL_VERSION_ID >= 50500
error_alloc_param_string:
#endif
  DBUG_RETURN(error);
}
Exemplo n.º 4
0
/*
  TODO:
       Add option --verify to mysqld to be able to change verification mode
*/
struct st_VioSSLAcceptorFd*
new_VioSSLAcceptorFd(const char *key_file,
		     const char *cert_file,
		     const char *ca_file,
		     const char *ca_path,
		     const char *cipher)
{
  int verify = (SSL_VERIFY_PEER			|
		SSL_VERIFY_CLIENT_ONCE);
  struct st_VioSSLAcceptorFd* ptr;
  int result;
  DH *dh=NULL; 
  DBUG_ENTER("new_VioSSLAcceptorFd");
  DBUG_PRINT("enter",
	     ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
	      key_file, cert_file, ca_path, ca_file, cipher));

  ptr= ((struct st_VioSSLAcceptorFd*)
	my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0)));
  ptr->ssl_context=0;
  ptr->ssl_method=0;
  /* FIXME: constants! */
  ptr->session_id_context= ptr;

  if (!ssl_algorithms_added)
  {
    DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
    ssl_algorithms_added = TRUE;
    OpenSSL_add_all_algorithms();

  }
  if (!ssl_error_strings_loaded)
  {
    DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
    ssl_error_strings_loaded = TRUE;
    SSL_load_error_strings();
  }
  ptr->ssl_method=  TLSv1_server_method();
  ptr->ssl_context= SSL_CTX_new(ptr->ssl_method);
  if (ptr->ssl_context == 0)
  {
    DBUG_PRINT("error", ("SSL_CTX_new failed"));
    report_errors();
    goto ctor_failure;
  }
  if (cipher)
  {
    result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
    DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
  }
  /* SSL_CTX_set_quiet_shutdown(ctx,1); */
  SSL_CTX_sess_set_cache_size(ptr->ssl_context,128);

  /* DH? */
  SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
  SSL_CTX_set_session_id_context(ptr->ssl_context,
				 (const uchar*) &(ptr->session_id_context),
				 sizeof(ptr->session_id_context));

  /*
    SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
  */
  if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
  {
    DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
    report_errors();
    goto ctor_failure;
  }
  if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0)
  {
    DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
    if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0)
    {
      DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
      report_errors();
      goto ctor_failure;
    }
  }
  /* DH stuff */
  dh=get_dh512();
  SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
  DH_free(dh);
  DBUG_RETURN(ptr);

ctor_failure:
  DBUG_PRINT("exit", ("there was an error"));
  my_free((gptr) ptr,MYF(0));
  DBUG_RETURN(0);
}
Exemplo n.º 5
0
#include "my_static.h"
#include "mysys_err.h"

	/*
	  Remove an open tempfile so that it doesn't survive
	  if we crash;	If the operating system doesn't support
	  this, just remember the file name for later removal
	*/

static my_bool cache_remove_open_tmp(IO_CACHE *cache __attribute__((unused)),
				     const char *name)
{
#if O_TEMPORARY == 0
#if !defined(CANT_DELETE_OPEN_FILES)
  /* The following should always succeed */
  (void) my_delete(name,MYF(MY_WME | ME_NOINPUT));
#else
  int length;
  if (!(cache->file_name=
	(char*) my_malloc((length=strlen(name)+1),MYF(MY_WME))))
  {
    my_close(cache->file,MYF(0));
    cache->file = -1;
    errno=my_errno=ENOMEM;
    return 1;
  }
  memcpy(cache->file_name,name,length);
#endif
#endif /* O_TEMPORARY == 0 */
  return 0;
}
Exemplo n.º 6
0
int _mi_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length,
		   int flag)
{
  uint read_length,in_buff_length;
  my_off_t offset;
  uchar *in_buff_pos;
  DBUG_ENTER("_mi_read_cache");
  DBUG_ASSERT(!(info->myflags & MY_ENCRYPT));

  if (pos < info->pos_in_file)
  {
    read_length=length;
    if ((my_off_t) read_length > (my_off_t) (info->pos_in_file-pos))
      read_length=(uint) (info->pos_in_file-pos);
    info->seek_not_done=1;
    if (mysql_file_pread(info->file, buff, read_length, pos, MYF(MY_NABP)))
      DBUG_RETURN(1);
    if (!(length-=read_length))
      DBUG_RETURN(0);
    pos+=read_length;
    buff+=read_length;
  }
  if (pos >= info->pos_in_file &&
      (offset= (my_off_t) (pos - info->pos_in_file)) <
      (my_off_t) (info->read_end - info->request_pos))
  {
    in_buff_pos=info->request_pos+(uint) offset;
    in_buff_length= MY_MIN(length, (size_t) (info->read_end-in_buff_pos));
    memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
    if (!(length-=in_buff_length))
      DBUG_RETURN(0);
    pos+=in_buff_length;
    buff+=in_buff_length;
  }
  else
    in_buff_length=0;
  if (flag & READING_NEXT)
  {
    if (pos != (info->pos_in_file +
		(uint) (info->read_end - info->request_pos)))
    {
      info->pos_in_file=pos;				/* Force start here */
      info->read_pos=info->read_end=info->request_pos;	/* Everything used */
      info->seek_not_done=1;
    }
    else
      info->read_pos=info->read_end;			/* All block used */
    if (!_my_b_read(info,buff,length))
      DBUG_RETURN(0);
    read_length=info->error;
  }
  else
  {
    info->seek_not_done=1;
    if ((read_length= mysql_file_pread(info->file, buff, length, pos,
                                       MYF(0))) == length)
      DBUG_RETURN(0);
  }
  if (!(flag & READING_HEADER) || (int) read_length == -1 ||
      read_length+in_buff_length < 3)
  {
    DBUG_PRINT("error",
               ("Error %d reading next-multi-part block (Got %d bytes)",
                my_errno, (int) read_length));
    if (!my_errno || my_errno == -1 || my_errno == HA_ERR_FILE_TOO_SHORT)
      my_errno= HA_ERR_WRONG_IN_RECORD;
    DBUG_RETURN(1);
  }
  bzero(buff+read_length,MI_BLOCK_INFO_HEADER_LENGTH - in_buff_length -
        read_length);
  DBUG_RETURN(0);
} /* _mi_read_cache */
Exemplo n.º 7
0
MRN_API my_bool mroonga_normalize_init(UDF_INIT *initid, UDF_ARGS *args,
                                       char *message)
{
  st_mrn_normalize_info *info = NULL;
  String *result_str = NULL;

  initid->ptr = NULL;
  if (!(1 <= args->arg_count && args->arg_count <= 2)) {
    sprintf(message,
            "mroonga_normalize(): Incorrect number of arguments: %u for 1..2",
            args->arg_count);
    goto error;
  }
  if (args->arg_type[0] != STRING_RESULT) {
    strcpy(message,
           "mroonga_normalize(): The 1st argument must be query as string");
    goto error;
  }
  if (args->arg_count == 2) {
    if (args->arg_type[1] != STRING_RESULT) {
      strcpy(message,
             "mroonga_normalize(): "
             "The 2st argument must be normalizer name as string");
      goto error;
    }
  }

  initid->maybe_null = 1;
  initid->const_item = 0;

  info = (st_mrn_normalize_info *)mrn_my_malloc(sizeof(st_mrn_normalize_info),
                                                MYF(MY_WME | MY_ZEROFILL));
  if (!info) {
    strcpy(message, "mroonga_normalize(): out of memory");
    goto error;
  }

  info->ctx = mrn_context_pool->pull();
  {
    const char *current_db_path = MRN_THD_DB_PATH(current_thd);
    const char *action;
    if (current_db_path) {
      action = "open database";
      mrn::Database *db;
      int error = mrn_db_manager->open(current_db_path, &db);
      if (error == 0) {
        info->db = db->get();
        grn_ctx_use(info->ctx, info->db);
        info->use_shared_db = true;
      }
    } else {
      action = "create anonymous database";
      info->db = grn_db_create(info->ctx, NULL, NULL);
      info->use_shared_db = false;
    }
    if (!info->db) {
      sprintf(message,
              "mroonga_normalize(): failed to %s: %s",
              action,
              info->ctx->errbuf);
      goto error;
    }
  }

  if (args->arg_count == 1) {
    info->normalizer = grn_ctx_get(info->ctx, DEFAULT_NORMALIZER_NAME, -1);
  } else {
    info->normalizer = grn_ctx_get(info->ctx, args->args[1], args->lengths[1]);
  }
  if (!info->normalizer) {
    sprintf(message, "mroonga_normalize(): nonexistent normalizer %.*s",
            (int)args->lengths[1], args->args[1]);
    goto error;
  }
  info->flags = 0;

  result_str = &(info->result_str);
  mrn::encoding::set_raw(info->ctx, system_charset_info);
  result_str->set_charset(system_charset_info);

  initid->ptr = (char *)info;

  return FALSE;

error:
  if (info) {
    if (!info->use_shared_db) {
      grn_obj_close(info->ctx, info->db);
    }
    mrn_context_pool->release(info->ctx);
    my_free(info);
  }
  return TRUE;
}
int
main(int argc, char **argv)
{
	gcry_error_t 		gcry_error;
	File filein = 0;
	File fileout = 0;

	MY_INIT(argv[0]);

	if (get_options(&argc, &argv)) {
		goto err;
	}

	/* Acording to gcrypt docs (and my testing), setting up the threading
	   callbacks must be done first, so, lets give it a shot */
	gcry_error = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
	if (gcry_error) {
		msg("%s: unable to set libgcrypt thread cbs - "
		    "%s : %s\n", my_progname,
		    gcry_strsource(gcry_error),
		    gcry_strerror(gcry_error));
		return 1;
	}

	/* Version check should be the very first call because it
	makes sure that important subsystems are intialized. */
	if (!gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) {
		const char	*gcrypt_version;
		gcrypt_version = gcry_check_version(NULL);
		/* No other library has already initialized libgcrypt. */
		if (!gcrypt_version) {
			msg("%s: failed to initialize libgcrypt\n",
			    my_progname);
			return 1;
		} else if (opt_verbose) {
			msg("%s: using gcrypt %s\n", my_progname,
			    gcrypt_version);
		}
	}
	gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

	/* Determine the algorithm */
	encrypt_algo = encrypt_algos[opt_encrypt_algo];

	/* Set up the iv length */
	encrypt_iv_len = gcry_cipher_get_algo_blklen(encrypt_algo);

	/* Now set up the key */
	if (opt_encrypt_key == NULL && opt_encrypt_key_file == NULL) {
		msg("%s: no encryption key or key file specified.\n",
		    my_progname);
		return 1;
	} else if (opt_encrypt_key && opt_encrypt_key_file) {
		msg("%s: both encryption key and key file specified.\n",
		    my_progname);
		return 1;
	} else if (opt_encrypt_key_file) {
		if (!xb_crypt_read_key_file(opt_encrypt_key_file,
					    &opt_encrypt_key,
					    &encrypt_key_len)) {
			msg("%s: unable to read encryption key file \"%s\".\n",
			    opt_encrypt_key_file, my_progname);
			return 1;
		}
	} else {
		encrypt_key_len = strlen(opt_encrypt_key);
	}

	if (opt_input_file) {
		MY_STAT 	mystat;

		if (opt_verbose)
			msg("%s: input file \"%s\".\n", my_progname,
			    opt_input_file);

		if (my_stat(opt_input_file, &mystat, MYF(MY_WME)) == NULL) {
			goto err;
		}
		if (!MY_S_ISREG(mystat.st_mode)) {
			msg("%s: \"%s\" is not a regular file, exiting.\n",
			    my_progname, opt_input_file);
			goto err;
		}
		if ((filein = my_open(opt_input_file, O_RDONLY, MYF(MY_WME)))
		     < 0) {
			msg("%s: failed to open \"%s\".\n", my_progname,
			     opt_input_file);
			goto err;
		}
	} else {
		if (opt_verbose)
			msg("%s: input from standard input.\n", my_progname);
		filein = fileno(stdin);
	}

	if (opt_output_file) {
		if (opt_verbose)
			msg("%s: output file \"%s\".\n", my_progname,
			    opt_output_file);

		if ((fileout = my_create(opt_output_file, 0,
					 O_WRONLY|O_BINARY|O_EXCL|O_NOFOLLOW,
					 MYF(MY_WME))) < 0) {
			msg("%s: failed to create output file \"%s\".\n",
			    my_progname, opt_output_file);
			goto err;
		}
	} else {
		if (opt_verbose)
			msg("%s: output to standard output.\n", my_progname);
		fileout = fileno(stdout);
	}

	if (opt_run_mode == RUN_MODE_DECRYPT
	    && mode_decrypt(filein, fileout)) {
		goto err;
	} else if (opt_run_mode == RUN_MODE_ENCRYPT
		   && mode_encrypt(filein, fileout)) {
		goto err;
	}

	if (opt_input_file && filein) {
		my_close(filein, MYF(MY_WME));
	}
	if (opt_output_file && fileout) {
		my_close(fileout, MYF(MY_WME));
	}

	my_cleanup_options(my_long_options);

	my_end(0);

	return EXIT_SUCCESS;
err:
	if (opt_input_file && filein) {
		my_close(filein, MYF(MY_WME));
	}
	if (opt_output_file && fileout) {
		my_close(fileout, MYF(MY_WME));
	}

	my_cleanup_options(my_long_options);

	my_end(0);

	exit(EXIT_FAILURE);

}
static
int
mode_decrypt(File filein, File fileout)
{
	xb_rcrypt_t		*xbcrypt_file = NULL;
	void			*chunkbuf = NULL;
	size_t			chunksize;
	size_t			originalsize;
	void			*ivbuf = NULL;
	size_t			ivsize;
	void			*decryptbuf = NULL;
	size_t			decryptbufsize = 0;
	ulonglong		ttlchunksread = 0;
	ulonglong		ttlbytesread = 0;
	xb_rcrypt_result_t	result;
	gcry_cipher_hd_t	cipher_handle;
	gcry_error_t		gcry_error;

	if (encrypt_algo != GCRY_CIPHER_NONE) {
		gcry_error = gcry_cipher_open(&cipher_handle,
					      encrypt_algo,
					      encrypt_mode, 0);
		if (gcry_error) {
			msg("%s:decrypt: unable to open libgcrypt"
			    " cipher - %s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			return 1;
		}

		gcry_error = gcry_cipher_setkey(cipher_handle,
						opt_encrypt_key,
						encrypt_key_len);
		if (gcry_error) {
			msg("%s:decrypt: unable to set libgcrypt cipher"
			    "key - %s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			goto err;
		}
	}

	/* Initialize the xb_crypt format reader */
	xbcrypt_file = xb_crypt_read_open(&filein, my_xb_crypt_read_callback);
	if (xbcrypt_file == NULL) {
		msg("%s:decrypt: xb_crypt_read_open() failed.\n", my_progname);
		goto err;
	}

	/* Walk the encrypted chunks, decrypting them and writing out */
	while ((result = xb_crypt_read_chunk(xbcrypt_file, &chunkbuf,
					     &originalsize, &chunksize,
					     &ivbuf, &ivsize))
		== XB_CRYPT_READ_CHUNK) {

		if (encrypt_algo != GCRY_CIPHER_NONE) {
			gcry_error = gcry_cipher_reset(cipher_handle);
			if (gcry_error) {
				msg("%s:decrypt: unable to reset libgcrypt"
				    " cipher - %s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				goto err;
			}

			if (ivsize) {
				gcry_error = gcry_cipher_setiv(cipher_handle,
							       ivbuf,
							       ivsize);
			} else {
				gcry_error = gcry_cipher_setiv(cipher_handle,
							       v1_encrypt_iv,
							       encrypt_iv_len);
			}
			if (gcry_error) {
				msg("%s:decrypt: unable to set cipher iv - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				continue;
			}

			if (decryptbufsize < originalsize) {
				if (decryptbufsize) {
					decryptbuf = my_realloc(decryptbuf,
								originalsize,
								MYF(MY_WME));
					decryptbufsize = originalsize;
				} else {
					decryptbuf = my_malloc(originalsize,
							       MYF(MY_WME));
					decryptbufsize = originalsize;
				}
			}

			/* Try to decrypt it */
			gcry_error = gcry_cipher_decrypt(cipher_handle,
							 decryptbuf,
							 originalsize,
							 chunkbuf,
							 chunksize);
			if (gcry_error) {
				msg("%s:decrypt: unable to decrypt chunk - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				gcry_cipher_close(cipher_handle);
					goto err;
			}

		} else {
			decryptbuf = chunkbuf;
		}

		/* Write it out */
		if (my_write(fileout, decryptbuf, originalsize,
			     MYF(MY_WME | MY_NABP))) {
			msg("%s:decrypt: unable to write output chunk.\n",
			    my_progname);
			goto err;
		}
		ttlchunksread++;
		ttlbytesread += chunksize;
		if (opt_verbose)
			msg("%s:decrypt: %llu chunks read, %llu bytes read\n.",
		    	    my_progname, ttlchunksread, ttlbytesread);
	}

	xb_crypt_read_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (decryptbuf && decryptbufsize)
		my_free(decryptbuf);

	if (opt_verbose)
		msg("\n%s:decrypt: done\n", my_progname);

	return 0;
err:
	if (xbcrypt_file)
		xb_crypt_read_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (decryptbuf && decryptbufsize)
		my_free(decryptbuf);

	return 1;
}
Exemplo n.º 10
0
void reset_tree(TREE* tree)
{
  /* do not free mem_root, just mark blocks as free */
  free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
}
Exemplo n.º 11
0
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, 
                          void* custom_arg)
{
  int cmp;
  TREE_ELEMENT *element,***parent;

  parent= tree->parents;
  *parent = &tree->root; element= tree->root;
  for (;;)
  {
    if (element == &tree->null_element ||
	(cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
                                key)) == 0)
      break;
    if (cmp < 0)
    {
      *++parent= &element->right; element= element->right;
    }
    else
    {
      *++parent = &element->left; element= element->left;
    }
  }
  if (element == &tree->null_element)
  {
    uint alloc_size=sizeof(TREE_ELEMENT)+key_size+tree->size_of_element;
    tree->allocated+=alloc_size;

    if (tree->memory_limit && tree->elements_in_tree
                           && tree->allocated > tree->memory_limit)
    {
      reset_tree(tree);
      return tree_insert(tree, key, key_size, custom_arg);
    }

    key_size+=tree->size_of_element;
    if (tree->with_delete)
      element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
    else
      element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size);
    if (!element)
      return(NULL);
    **parent=element;
    element->left=element->right= &tree->null_element;
    if (!tree->offset_to_key)
    {
      if (key_size == sizeof(void*))		 /* no length, save pointer */
	*((void**) (element+1))=key;
      else
      {
	*((void**) (element+1))= (void*) ((void **) (element+1)+1);
	memcpy((uchar*) *((void **) (element+1)),key,
	       (size_t) (key_size-sizeof(void*)));
      }
    }
    else
      memcpy((uchar*) element+tree->offset_to_key,key,(size_t) key_size);
    element->count=1;			/* May give warning in purify */
    tree->elements_in_tree++;
    rb_insert(tree,parent,element);	/* rebalance tree */
  }
  else
  {
    if (tree->flag & TREE_NO_DUPS)
      return(NULL);
    element->count++;
    /* Avoid a wrap over of the count. */
    if (! element->count)
      element->count--;
  }
  DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
Exemplo n.º 12
0
void delete_tree(TREE* tree)
{
  free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */
}
Exemplo n.º 13
0
int my_copy(const char *from, const char *to, myf MyFlags)
{
  size_t Count;
  my_bool new_file_stat= 0; /* 1 if we could stat "to" */
  int create_flag;
  File from_file,to_file;
  uchar buff[IO_SIZE];
  MY_STAT stat_buff,new_stat_buff;
  DBUG_ENTER("my_copy");
  DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));

  from_file=to_file= -1;
  DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */
  if (MyFlags & MY_HOLD_ORIGINAL_MODES)		/* Copy stat if possible */
    new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0)));

  if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0)
  {
    if (!my_stat(from, &stat_buff, MyFlags))
    {
      my_errno=errno;
      goto err;
    }
    if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
      stat_buff=new_stat_buff;
    create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC;

    if ((to_file=  my_create(to,(int) stat_buff.st_mode,
			     O_WRONLY | create_flag | O_BINARY | O_SHARE,
			     MyFlags)) < 0)
      goto err;

    while ((Count=my_read(from_file, buff, sizeof(buff), MyFlags)) != 0)
    {
	if (Count == (uint) -1 ||
	    my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP)))
	goto err;
    }

    /* sync the destination file */
    if (MyFlags & MY_SYNC)
    {
      if (my_sync(to_file, MyFlags))
        goto err;
    }

    if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags))
      DBUG_RETURN(-1);				/* Error on close */

    /* Copy modes if possible */

    if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
	DBUG_RETURN(0);			/* File copyed but not stat */
    /* Copy modes */
    if (chmod(to, stat_buff.st_mode & 07777))
    {
      my_errno= errno;
      if (MyFlags & (MY_FAE+MY_WME))
        my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno);
      goto err;
    }
#if !defined(__WIN__)
    /* Copy ownership */
    if (chown(to, stat_buff.st_uid, stat_buff.st_gid))
    {
      my_errno= errno;
      if (MyFlags & (MY_FAE+MY_WME))
        my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno);
      goto err;
    }
#endif

    if (MyFlags & MY_COPYTIME)
    {
      struct utimbuf timep;
      timep.actime  = stat_buff.st_atime;
      timep.modtime = stat_buff.st_mtime;
      (void) utime((char*) to, &timep); /* last accessed and modified times */
    }

    DBUG_RETURN(0);
  }

err:
  if (from_file >= 0) (void) my_close(from_file,MyFlags);
  if (to_file >= 0)
  {
    (void) my_close(to_file, MyFlags);
    /* attempt to delete the to-file we've partially written */
    (void) my_delete(to, MyFlags);
  }
  DBUG_RETURN(-1);
} /* my_copy */
Exemplo n.º 14
0
File create_temp_file(char *to, const char *dir, const char *prefix,
                      int mode, myf MyFlags)
{
    File file= -1;
#ifdef _WIN32
    TCHAR path_buf[MAX_PATH-14];
#endif

    DBUG_ENTER("create_temp_file");
    DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
#if defined(_WIN32)

    /*
      Use GetTempPath to determine path for temporary files.
      This is because the documentation for GetTempFileName
      has the following to say about this parameter:
      "If this parameter is NULL, the function fails."
    */
    if (!dir)
    {
        if(GetTempPath(sizeof(path_buf), path_buf) > 0)
            dir = path_buf;
    }
    /*
      Use GetTempFileName to generate a unique filename, create
      the file and release it's handle
       - uses up to the first three letters from prefix
    */
    if (GetTempFileName(dir, prefix, 0, to) == 0)
        DBUG_RETURN(-1);

    DBUG_PRINT("info", ("name: %s", to));

    /*
      Open the file without the "open only if file doesn't already exist"
      since the file has already been created by GetTempFileName
    */
    if ((file= my_open(to,  (mode & ~O_EXCL), MyFlags)) < 0)
    {
        /* Open failed, remove the file created by GetTempFileName */
        int tmp= my_errno();
        (void) my_delete(to, MYF(0));
        set_my_errno(tmp);
    }

#else /* mkstemp() is available on all non-Windows supported platforms. */
    {
        char prefix_buff[30];
        uint pfx_len;
        File org_file;

        pfx_len= (uint) (my_stpcpy(my_stpnmov(prefix_buff,
                                              prefix ? prefix : "tmp.",
                                              sizeof(prefix_buff)-7),"XXXXXX") -
                         prefix_buff);
        if (!dir && ! (dir =getenv("TMPDIR")))
            dir= DEFAULT_TMPDIR;
        if (strlen(dir)+ pfx_len > FN_REFLEN-2)
        {
            errno=ENAMETOOLONG;
            set_my_errno(ENAMETOOLONG);
            DBUG_RETURN(file);
        }
        my_stpcpy(convert_dirname(to,dir,NullS),prefix_buff);
        org_file=mkstemp(to);
        if (mode & O_TEMPORARY)
            (void) my_delete(to, MYF(MY_WME));
        file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
                                  EE_CANTCREATEFILE, MyFlags);
        /* If we didn't manage to register the name, remove the temp file */
        if (org_file >= 0 && file < 0)
        {
            int tmp=my_errno();
            close(org_file);
            (void) my_delete(to, MYF(MY_WME));
            set_my_errno(tmp);
        }
    }
#endif
    if (file >= 0)
    {
        mysql_mutex_lock(&THR_LOCK_open);
        my_tmp_file_created++;
        mysql_mutex_unlock(&THR_LOCK_open);
    }
    DBUG_RETURN(file);
}
Exemplo n.º 15
0
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
  int save_errno,errpos=0;
  uint files= 0, i, dir_length, length, UNINIT_VAR(key_parts), min_keys= 0;
  ulonglong file_offset=0;
  char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
  MYRG_INFO *m_info=0;
  File fd;
  IO_CACHE file;
  MI_INFO *isam=0;
  uint found_merge_insert_method= 0;
  size_t name_buff_length;
  my_bool bad_children= FALSE;
  DBUG_ENTER("myrg_open");

  bzero((char*) &file,sizeof(file));
  if ((fd= mysql_file_open(rg_key_file_MRG,
                           fn_format(name_buff, name, "", MYRG_NAME_EXT,
                                     MY_UNPACK_FILENAME|MY_APPEND_EXT),
                           O_RDONLY | O_SHARE, MYF(0))) < 0)
    goto err;
  errpos=1;
  if (init_io_cache(&file, fd, 4*IO_SIZE, READ_CACHE, 0, 0,
		    MYF(MY_WME | MY_NABP)))
    goto err;
  errpos=2;
  dir_length=dirname_part(name_buff, name, &name_buff_length);
  while ((length=my_b_gets(&file,buff,FN_REFLEN-1)))
  {
    if ((end=buff+length)[-1] == '\n')
      end[-1]='\0';
    if (buff[0] && buff[0] != '#')
      files++;
  }

  my_b_seek(&file, 0);
  while ((length=my_b_gets(&file,buff,FN_REFLEN-1)))
  {
    if ((end=buff+length)[-1] == '\n')
      *--end='\0';
    if (!buff[0])
      continue;		/* Skip empty lines */
    if (buff[0] == '#')
    {
      if (!strncmp(buff+1,"INSERT_METHOD=",14))
      {			/* Lookup insert method */
	int tmp= find_type(buff + 15, &merge_insert_method, FIND_TYPE_BASIC);
	found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0);
      }
      continue;		/* Skip comments */
    }

    if (!has_path(buff))
    {
      (void) strmake(name_buff+dir_length,buff,
                   sizeof(name_buff)-1-dir_length);
      (void) cleanup_dirname(buff,name_buff);
    }
    else
      fn_format(buff, buff, "", "", 0);
    if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
    {
      if (handle_locking & HA_OPEN_FOR_REPAIR)
      {
        myrg_print_wrong_table(buff);
        bad_children= TRUE;
        continue;
      }
      goto bad_children;
    }
    if (!m_info)                                /* First file */
    {
      key_parts=isam->s->base.key_parts;
      if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) +
                                           files*sizeof(MYRG_TABLE) +
                                           key_parts*sizeof(long),
                                           MYF(MY_WME|MY_ZEROFILL))))
        goto err;
      DBUG_ASSERT(files);
      m_info->open_tables=(MYRG_TABLE *) (m_info+1);
      m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files);
      m_info->tables= files;
      files= 0;
      m_info->reclength=isam->s->base.reclength;
      min_keys= isam->s->base.keys;
      errpos=3;
    }
    m_info->open_tables[files].table= isam;
    m_info->open_tables[files].file_offset=(my_off_t) file_offset;
    file_offset+=isam->state->data_file_length;
    files++;
    if (m_info->reclength != isam->s->base.reclength)
    {
      if (handle_locking & HA_OPEN_FOR_REPAIR)
      {
        myrg_print_wrong_table(buff);
        bad_children= TRUE;
        continue;
      }
      goto bad_children;
    }
    m_info->options|= isam->s->options;
    m_info->records+= isam->state->records;
    m_info->del+= isam->state->del;
    m_info->data_file_length+= isam->state->data_file_length;
    if (min_keys > isam->s->base.keys)
      min_keys= isam->s->base.keys;
    for (i=0; i < key_parts; i++)
      m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
                                     m_info->tables);
  }

  if (bad_children)
    goto bad_children;
  if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO),
                                                  MYF(MY_WME | MY_ZEROFILL))))
    goto err;
  /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */
  m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
  m_info->merge_insert_method= found_merge_insert_method;

  if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
  {
    my_errno=HA_ERR_RECORD_FILE_FULL;
    goto err;
  }
  m_info->keys= min_keys;
  bzero((char*) &m_info->by_key,sizeof(m_info->by_key));

  /* this works ok if the table list is empty */
  m_info->end_table=m_info->open_tables+files;
  m_info->last_used_table=m_info->open_tables;
  m_info->children_attached= TRUE;

  (void) mysql_file_close(fd, MYF(0));
  end_io_cache(&file);
  mysql_mutex_init(rg_key_mutex_MYRG_INFO_mutex,
                   &m_info->mutex, MY_MUTEX_INIT_FAST);
  m_info->open_list.data=(void*) m_info;
  mysql_mutex_lock(&THR_LOCK_open);
  myrg_open_list=list_add(myrg_open_list,&m_info->open_list);
  mysql_mutex_unlock(&THR_LOCK_open);
  DBUG_RETURN(m_info);

bad_children:
  my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
err:
  save_errno=my_errno;
  switch (errpos) {
  case 3:
    while (files)
      (void) mi_close(m_info->open_tables[--files].table);
    my_free(m_info);
    /* Fall through */
  case 2:
    end_io_cache(&file);
    /* Fall through */
  case 1:
    (void) mysql_file_close(fd, MYF(0));
  }
  my_errno=save_errno;
  DBUG_RETURN (NULL);
}
static
int
mode_encrypt(File filein, File fileout)
{
	size_t			bytesread;
	size_t			chunkbuflen;
	void			*chunkbuf = NULL;
	void			*ivbuf = NULL;
	size_t			encryptbuflen = 0;
	size_t			encryptedlen = 0;
	void			*encryptbuf = NULL;
	ulonglong		ttlchunkswritten = 0;
	ulonglong		ttlbyteswritten = 0;
	xb_wcrypt_t		*xbcrypt_file = NULL;
	gcry_cipher_hd_t	cipher_handle;
	gcry_error_t		gcry_error;

	if (encrypt_algo != GCRY_CIPHER_NONE) {
		gcry_error = gcry_cipher_open(&cipher_handle,
					      encrypt_algo,
					      encrypt_mode, 0);
		if (gcry_error) {
			msg("%s:encrypt: unable to open libgcrypt cipher - "
			    "%s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			return 1;
		}

		gcry_error = gcry_cipher_setkey(cipher_handle,
						opt_encrypt_key,
						encrypt_key_len);
		if (gcry_error) {
			msg("%s:encrypt: unable to set libgcrypt cipher key - "
			    "%s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			goto err;
		}
	}

	posix_fadvise(filein, 0, 0, POSIX_FADV_SEQUENTIAL);

	xbcrypt_file = xb_crypt_write_open(&fileout,
					   my_xb_crypt_write_callback);
	if (xbcrypt_file == NULL) {
		msg("%s:encrypt: xb_crypt_write_open() failed.\n",
		    my_progname);
		goto err;
	}

	ivbuf = my_malloc(encrypt_iv_len, MYF(MY_FAE));

	/* now read in data in chunk size, encrypt and write out */
	chunkbuflen = opt_encrypt_chunk_size;
	chunkbuf = my_malloc(chunkbuflen, MYF(MY_FAE));
	while ((bytesread = my_read(filein, chunkbuf, chunkbuflen,
				    MYF(MY_WME))) > 0) {

		if (encrypt_algo != GCRY_CIPHER_NONE) {
			gcry_error = gcry_cipher_reset(cipher_handle);

			if (gcry_error) {
				msg("%s:encrypt: unable to reset cipher - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				goto err;
			}

			xb_crypt_create_iv(ivbuf, encrypt_iv_len);
			gcry_error = gcry_cipher_setiv(cipher_handle,
							ivbuf,
							encrypt_iv_len);

			if (gcry_error) {
				msg("%s:encrypt: unable to set cipher iv - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				continue;
			}

			if (encryptbuflen < bytesread) {
				if (encryptbuflen) {
					encryptbuf = my_realloc(encryptbuf,
								bytesread,
								MYF(MY_WME));
					encryptbuflen = bytesread;
				} else {
					encryptbuf = my_malloc(bytesread,
							       MYF(MY_WME));
					encryptbuflen = bytesread;
				}
			}

			gcry_error = gcry_cipher_encrypt(cipher_handle,
							 encryptbuf,
							 encryptbuflen,
							 chunkbuf,
							 bytesread);

			encryptedlen = bytesread;

			if (gcry_error) {
				msg("%s:encrypt: unable to encrypt chunk - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				gcry_cipher_close(cipher_handle);
				goto err;
			}
		} else {
			encryptedlen = bytesread;
			encryptbuf = chunkbuf;
		}

		if (xb_crypt_write_chunk(xbcrypt_file, encryptbuf, bytesread,
					 encryptedlen, ivbuf, encrypt_iv_len)) {
			msg("%s:encrypt: abcrypt_write_chunk() failed.\n",
			    my_progname);
			goto err;
		}

		ttlchunkswritten++;
		ttlbyteswritten += encryptedlen;

		if (opt_verbose)
			msg("%s:encrypt: %llu chunks written, %llu bytes "
			    "written\n.", my_progname, ttlchunkswritten,
			    ttlbyteswritten);
	}

	my_free(ivbuf);
	my_free(chunkbuf);

	if (encryptbuf && encryptbuflen)
		my_free(encryptbuf);

	xb_crypt_write_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (opt_verbose)
		msg("\n%s:encrypt: done\n", my_progname);

	return 0;
err:
	if (chunkbuf)
		my_free(chunkbuf);

	if (encryptbuf && encryptbuflen)
		my_free(encryptbuf);

	if (xbcrypt_file)
		xb_crypt_write_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	return 1;
}
Exemplo n.º 17
0
int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
                         MI_INFO *(*callback)(void*),
                         void *callback_param, my_bool *need_compat_check)
{
  ulonglong  file_offset;
  MI_INFO    *myisam;
  int        errpos;
  int        save_errno;
  uint       idx;
  uint       child_nr;
  uint       UNINIT_VAR(key_parts);
  uint       min_keys;
  my_bool    bad_children= FALSE;
  my_bool    first_child= TRUE;
  DBUG_ENTER("myrg_attach_children");
  DBUG_PRINT("myrg", ("handle_locking: %d", handle_locking));

  /*
    This function can be called while another thread is trying to abort
    locks of this MERGE table. If the processor reorders instructions or
    write to memory, 'children_attached' could be set before
    'open_tables' has all the pointers to the children. Use of a mutex
    here and in ha_myisammrg::store_lock() forces consistent data.
  */
  mysql_mutex_lock(&m_info->mutex);
  errpos= 0;
  file_offset= 0;
  min_keys= 0;
  for (child_nr= 0; child_nr < m_info->tables; child_nr++)
  {
    if (! (myisam= (*callback)(callback_param)))
    {
      if (handle_locking & HA_OPEN_FOR_REPAIR)
      {
        /* An appropriate error should've been already pushed by callback. */
        bad_children= TRUE;
        continue;
      }
      goto bad_children;
    }

    DBUG_PRINT("myrg", ("child_nr: %u  table: '%s'",
                        child_nr, myisam->filename));

    /* Special handling when the first child is attached. */
    if (first_child)
    {
      first_child= FALSE;
      m_info->reclength= myisam->s->base.reclength;
      min_keys=  myisam->s->base.keys;
      key_parts= myisam->s->base.key_parts;
      if (*need_compat_check && m_info->rec_per_key_part)
      {
        my_free(m_info->rec_per_key_part);
        m_info->rec_per_key_part= NULL;
      }
      if (!m_info->rec_per_key_part)
      {
        if(!(m_info->rec_per_key_part= (ulong*)
             my_malloc(key_parts * sizeof(long), MYF(MY_WME))))
          goto err; /* purecov: inspected */
        errpos= 1;
      }
      bzero((char*) m_info->rec_per_key_part, key_parts * sizeof(long));
    }

    /* Add MyISAM table info. */
    m_info->open_tables[child_nr].table= myisam;
    m_info->open_tables[child_nr].file_offset= (my_off_t) file_offset;
    file_offset+= myisam->state->data_file_length;

    /* Check table definition match. */
    if (m_info->reclength != myisam->s->base.reclength)
    {
      DBUG_PRINT("error", ("definition mismatch table: '%s'  repair: %d",
                           myisam->filename,
                           (handle_locking & HA_OPEN_FOR_REPAIR)));
      if (handle_locking & HA_OPEN_FOR_REPAIR)
      {
        myrg_print_wrong_table(myisam->filename);
        bad_children= TRUE;
        continue;
      }
      goto bad_children;
    }

    m_info->options|= myisam->s->options;
    m_info->records+= myisam->state->records;
    m_info->del+= myisam->state->del;
    m_info->data_file_length+= myisam->state->data_file_length;
    if (min_keys > myisam->s->base.keys)
      min_keys= myisam->s->base.keys; /* purecov: inspected */
    for (idx= 0; idx < key_parts; idx++)
      m_info->rec_per_key_part[idx]+= (myisam->s->state.rec_per_key_part[idx] /
                                       m_info->tables);
  }

  if (bad_children)
    goto bad_children;

  if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
  {
    my_errno= HA_ERR_RECORD_FILE_FULL;
    goto err;
  }
  /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */
  m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
  m_info->keys= min_keys;
  m_info->last_used_table= m_info->open_tables;
  m_info->children_attached= TRUE;
  mysql_mutex_unlock(&m_info->mutex);
  DBUG_RETURN(0);

bad_children:
  my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
err:
  save_errno= my_errno;
  switch (errpos) {
  case 1:
    my_free(m_info->rec_per_key_part);
    m_info->rec_per_key_part= NULL;
  }
  mysql_mutex_unlock(&m_info->mutex);
  my_errno= save_errno;
  DBUG_RETURN(1);
}
Exemplo n.º 18
0
/*
  Change size of file.

  SYNOPSIS
    my_chsize()
      fd		File descriptor
      new_length	New file size
      filler		If we don't have truncate, fill up all bytes after
			new_length with this character
      MyFlags		Flags

  DESCRIPTION
    my_chsize() truncates file if shorter else fill with the filler character.
    The function also changes the file pointer. Usually it points to the end
    of the file after execution.

  RETURN VALUE
    0	Ok
    1	Error
*/
int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
{
  my_off_t oldsize;
  uchar buff[IO_SIZE];
  DBUG_ENTER("my_chsize");
  DBUG_PRINT("my",("fd: %d  length: %lu  MyFlags: %d",fd,(ulong) newlength,
		   MyFlags));

  if ((oldsize= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength)
    DBUG_RETURN(0);

  DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));

  if (oldsize > newlength)
  {
#ifdef _WIN32
    if (my_win_chsize(fd, newlength))
    {
      my_errno= errno;
      goto err;
    }
    DBUG_RETURN(0);
#elif defined(HAVE_FTRUNCATE)
    if (ftruncate(fd, (off_t) newlength))
    {
      my_errno= errno;
      goto err;
    }
    DBUG_RETURN(0);
#elif defined(HAVE_CHSIZE)
    if (chsize(fd, (off_t) newlength))
    {
      my_errno=errno;
      goto err;
    }
    DBUG_RETURN(0);
#else
    /*
      Fill space between requested length and true length with 'filler'
      We should never come here on any modern machine
    */
    if (my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE))
        == MY_FILEPOS_ERROR)
    {
      goto err;
    }
    swap_variables(my_off_t, newlength, oldsize);
#endif
  }

  /* Full file with 'filler' until it's as big as requested */
  bfill(buff, IO_SIZE, filler);
  while (newlength-oldsize > IO_SIZE)
  {
    if (my_write(fd, buff, IO_SIZE, MYF(MY_NABP)))
      goto err;
    oldsize+= IO_SIZE;
  }
  if (my_write(fd,buff,(size_t) (newlength-oldsize), MYF(MY_NABP)))
    goto err;
  DBUG_RETURN(0);

err:
  DBUG_PRINT("error", ("errno: %d", errno));
  if (MyFlags & MY_WME)
    my_error(EE_CANT_CHSIZE, MYF(ME_BELL+ME_WAITTANG), my_errno);
  DBUG_RETURN(1);
} /* my_chsize */
Exemplo n.º 19
0
int main(int argc, char **argv)
{
  int error;
  my_bool first_argument_uses_wildcards=0;
  char *wild;
  MYSQL mysql;
  MY_INIT(argv[0]);
  load_defaults("my",load_default_groups,&argc,&argv);
  get_options(&argc,&argv);

  wild=0;
  if (argc)
  {
    char *pos= argv[argc-1], *to;
    for (to= pos ; *pos ; pos++, to++)
    {
      switch (*pos) {
      case '*':
	*pos= '%';
	first_argument_uses_wildcards= 1;
	break;
      case '?':
	*pos= '_';
	first_argument_uses_wildcards= 1;
	break;
      case '%':
      case '_':
	first_argument_uses_wildcards= 1;
	break;
      case '\\':
	pos++;
      default: break;
      }
      *to= *pos;
    }    
    *to= *pos; /* just to copy a '\0'  if '\\' was used */
  }
  if (first_argument_uses_wildcards)
    wild= argv[--argc];
  else if (argc == 3)			/* We only want one field */
    wild= argv[--argc];

  if (argc > 2)
  {
    fprintf(stderr,"%s: Too many arguments\n",my_progname);
    exit(1);
  }
  mysql_init(&mysql);
  if (opt_compress)
    mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
  if (opt_use_ssl)
    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
		  opt_ssl_capath, opt_ssl_cipher);
  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                (char*)&opt_ssl_verify_server_cert);
#endif
  if (opt_protocol)
    mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
#ifdef HAVE_SMEM
  if (shared_memory_base_name)
    mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
  mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);

  if (!(mysql_real_connect(&mysql,host,user,opt_password,
			   (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port,
			   0)))
  {
    fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
    exit(1);
  }
  mysql.reconnect= 1;

  switch (argc)
  {
  case 0:  error=list_dbs(&mysql,wild); break;
  case 1:
    if (opt_status)
      error=list_table_status(&mysql,argv[0],wild);
    else
      error=list_tables(&mysql,argv[0],wild);
    break;
  default:
    if (opt_status && ! wild)
      error=list_table_status(&mysql,argv[0],argv[1]);
    else
      error=list_fields(&mysql,argv[0],argv[1],wild);
    break;
  }
  mysql_close(&mysql);			/* Close & free connection */
  if (opt_password)
    my_free(opt_password,MYF(0));
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
  my_end(0);
  exit(error ? 1 : 0);
  return 0;				/* No compiler warnings */
}
Exemplo n.º 20
0
/* {{{ MADB_SetIrdRecord */
my_bool
MADB_SetIrdRecord(MADB_Stmt *Stmt, MADB_DescRecord *Record, MYSQL_FIELD *Field)
{
  if (Record == NULL)
  {
    return 1;
  }

  Record->CatalogName= Field->catalog ? my_strdup(Field->catalog, MYF(0)) : NULL;
  Record->TableName= Field->table ? my_strdup(Field->table, MYF(0)) : NULL;
  Record->ColumnName= Field->name ? my_strdup(Field->name, MYF(0)) : NULL;
  Record->BaseTableName= Field->org_table ? my_strdup(Field->org_table, MYF(0)) : NULL;
  Record->BaseColumnName= Field->org_name ? my_strdup(Field->org_name, MYF(0)) : NULL;
  Record->AutoUniqueValue= (Field->flags & AUTO_INCREMENT_FLAG) ? SQL_TRUE : SQL_FALSE;
  Record->CaseSensitive= (Field->flags & BINARY_FLAG) ? SQL_TRUE : SQL_FALSE;
  Record->Nullable= ( (Field->flags & NOT_NULL_FLAG) &&
                      !Record->AutoUniqueValue &&
                      Field->type != MYSQL_TYPE_TIMESTAMP) ? SQL_NO_NULLS : SQL_NULLABLE;
  Record->Unsigned= (Field->flags & UNSIGNED_FLAG) ? SQL_TRUE : SQL_FALSE;
  /* We assume it might be updatable if tablename exists */
  Record->Updateable= (Field->table && Field->table[0]) ? SQL_ATTR_READWRITE_UNKNOWN : SQL_ATTR_READONLY;

  /*
      RADIX:
      If the data type in the SQL_DESC_TYPE field is an approximate numeric data type, this SQLINTEGER field 
      contains a value of 2 because the SQL_DESC_PRECISION field contains the number of bits. 
      If the data type in the SQL_DESC_TYPE field is an exact numeric data type, this field contains a value of 10 
      because the SQL_DESC_PRECISION field contains the number of decimal digits. 
      This field is set to 0 for all non-numeric data types.
  */
  switch (Field->type) {
  case MYSQL_TYPE_DECIMAL:
  case MYSQL_TYPE_NEWDECIMAL:
    Record->FixedPrecScale= SQL_FALSE;
    Record->NumPrecRadix= 10;
    Record->Precision= (SQLSMALLINT)Field->length - 2;
    Record->Scale= Field->decimals;
    break;
  case MYSQL_TYPE_FLOAT:
    Record->FixedPrecScale= SQL_FALSE;
    Record->NumPrecRadix= 2;
    Record->Precision= (SQLSMALLINT)Field->length - 2;
    //Record->Scale= Field->decimals;
    break;
  case MYSQL_TYPE_BIT:
    if (Field->length > 1)
      Record->Type= SQL_BINARY;
    break;
  case MYSQL_TYPE_DOUBLE:
  case MYSQL_TYPE_TINY:
  case MYSQL_TYPE_SHORT:
  case MYSQL_TYPE_INT24:
  case MYSQL_TYPE_YEAR:
  case MYSQL_TYPE_LONG:
  case MYSQL_TYPE_LONGLONG:
    Record->NumPrecRadix= 10;
    break;
  default:
    Record->NumPrecRadix= 0;
    break;
  }
  Record->ConciseType= MADB_GetODBCType(Field);
  /* 
      TYPE:
      For the datetime and interval data types, this field returns the verbose data type: SQL_DATETIME or SQL_INTERVAL.
  */
  Record->Type= (Record->ConciseType ==  SQL_TYPE_DATE || Record->ConciseType ==  SQL_DATE ||
                  Record->ConciseType ==  SQL_TYPE_TIME || Record->ConciseType ==  SQL_TIME ||
                  Record->ConciseType ==  SQL_TYPE_TIMESTAMP || Record->ConciseType == SQL_TIMESTAMP) ?
                    SQL_DATETIME : Record->ConciseType;

  switch(Record->ConciseType) {
  case SQL_TYPE_DATE:
    Record->DateTimeIntervalCode= SQL_CODE_DATE;
    break;
  case SQL_TYPE_TIME:
    Record->DateTimeIntervalCode= SQL_CODE_TIME;
    break;
  case SQL_TYPE_TIMESTAMP:
    Record->DateTimeIntervalCode= SQL_CODE_TIMESTAMP;
    break;
  }
  /* 
      SEARCHABLE:
      Columns of type SQL_LONGVARCHAR and SQL_LONGVARBINARY usually return SQL_PRED_CHAR.
  */
  Record->Searchable= (Record->ConciseType == SQL_LONGVARCHAR ||
                        Record->ConciseType == SQL_WLONGVARCHAR ||
                        Record->ConciseType == SQL_LONGVARBINARY) ? SQL_PRED_CHAR : SQL_SEARCHABLE;

  Record->DisplaySize= MADB_GetDisplaySize(*Field, mysql_get_charset_by_nr(Field->charsetnr));
  Record->OctetLength= MADB_GetOctetLength(*Field, Stmt->Connection->mariadb->charset->char_maxlen);
  Record->Length= MADB_GetDataSize(Record, *Field, mysql_get_charset_by_nr(Field->charsetnr));
    
  Record->TypeName= my_strdup(MADB_GetTypeName(*Field), MYF(0));
  switch(Field->type) {
  case MYSQL_TYPE_BLOB:
  case MYSQL_TYPE_LONG_BLOB:
  case MYSQL_TYPE_MEDIUM_BLOB:
  case MYSQL_TYPE_STRING:
  case MYSQL_TYPE_TINY_BLOB:
  case MYSQL_TYPE_VAR_STRING:
    if (Field->flags & BINARY_FLAG)
    {
      Record->LiteralPrefix= "0x";
      Record->LiteralSuffix= "";
      break;
    }
    /* else default */
  case MYSQL_TYPE_DATE:
  case MYSQL_TYPE_DATETIME:
  case MYSQL_TYPE_NEWDATE:
  case MYSQL_TYPE_TIME:
  case MYSQL_TYPE_TIMESTAMP:
  case MYSQL_TYPE_YEAR:
    Record->LiteralPrefix="'";
    Record->LiteralSuffix= "'";
    break;
  default:
    Record->LiteralPrefix= "";
    Record->LiteralSuffix= "";
    break;
  }

  return 0;
}
Exemplo n.º 21
0
struct st_VioSSLConnectorFd *
new_VioSSLConnectorFd(const char* key_file,
		      const char* cert_file,
		      const char* ca_file,
		      const char* ca_path,
		      const char* cipher)
{
  int	verify = SSL_VERIFY_NONE;
  struct st_VioSSLConnectorFd* ptr;
  int result;
  DH *dh=NULL; 
  DBUG_ENTER("new_VioSSLConnectorFd");
  DBUG_PRINT("enter",
	     ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
	      key_file, cert_file, ca_path, ca_file, cipher));

  if (!(ptr=((struct st_VioSSLConnectorFd*)
	     my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0)))))
    DBUG_RETURN(0);

  ptr->ssl_context= 0;
  ptr->ssl_method=  0;
  /* FIXME: constants! */

  if (!ssl_algorithms_added)
  {
    DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
    ssl_algorithms_added = TRUE;
    OpenSSL_add_all_algorithms();
  }
  if (!ssl_error_strings_loaded)
  {
    DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
    ssl_error_strings_loaded = TRUE;
    SSL_load_error_strings();
  }
  ptr->ssl_method = TLSv1_client_method();
  ptr->ssl_context = SSL_CTX_new(ptr->ssl_method);
  DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context));
  if (ptr->ssl_context == 0)
  {
    DBUG_PRINT("error", ("SSL_CTX_new failed"));
    report_errors();
    goto ctor_failure;
  }
  /*
    SSL_CTX_set_options
    SSL_CTX_set_info_callback
   */
  if (cipher)
  {
    result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
    DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
  }
  SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
  if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
  {
    DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
    report_errors();
    goto ctor_failure;
  }
  if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0)
  {
    DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
    if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0)
    {
      DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
      report_errors();
      goto ctor_failure;
    }
  } 

  /* DH stuff */
  dh=get_dh512();
  SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
  DH_free(dh);

  DBUG_RETURN(ptr);
ctor_failure:
  DBUG_PRINT("exit", ("there was an error"));
  my_free((gptr)ptr,MYF(0));
  DBUG_RETURN(0);
}
Exemplo n.º 22
0
static int add_collation(CHARSET_INFO *cs)
{
  if (cs->name && (cs->number ||
                   (cs->number=get_collation_number_internal(cs->name))) &&
      cs->number < array_elements(all_charsets))
  {
    if (!all_charsets[cs->number])
    {
      if (!(all_charsets[cs->number]=
         (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
        return MY_XML_ERROR;
      memset(all_charsets[cs->number], 0, sizeof(CHARSET_INFO));
    }
    
    if (cs->primary_number == cs->number)
      cs->state |= MY_CS_PRIMARY;
      
    if (cs->binary_number == cs->number)
      cs->state |= MY_CS_BINSORT;
    
    all_charsets[cs->number]->state|= cs->state;
    
    if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
    {
      CHARSET_INFO *newcs= all_charsets[cs->number];
      if (cs_copy_data(all_charsets[cs->number],cs))
        return MY_XML_ERROR;

      newcs->caseup_multiply= newcs->casedn_multiply= 1;
      newcs->levels_for_compare= 1;
      newcs->levels_for_order= 1;
      
      if (!strcmp(cs->csname,"ucs2") )
      {
#if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS)
        copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci);
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
#endif        
      }
      else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3"))
      {
#if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS)
        copy_uca_collation(newcs, &my_charset_utf8_unicode_ci);
        newcs->ctype= my_charset_utf8_unicode_ci.ctype;
        if (init_state_maps(newcs))
          return MY_XML_ERROR;
#endif
      }
      else if (!strcmp(cs->csname, "utf8mb4"))
      {
#if defined (HAVE_CHARSET_utf8mb4) && defined(HAVE_UCA_COLLATIONS)
        copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci);
        newcs->ctype= my_charset_utf8mb4_unicode_ci.ctype;
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED;
#endif
      }
      else if (!strcmp(cs->csname, "utf16"))
      {
#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS)
        copy_uca_collation(newcs, &my_charset_utf16_unicode_ci);
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
#endif
      }
      else if (!strcmp(cs->csname, "utf32"))
      {
#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS)
        copy_uca_collation(newcs, &my_charset_utf32_unicode_ci);
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
#endif
      }
      else
      {
        const uchar *sort_order= all_charsets[cs->number]->sort_order;
        simple_cs_init_functions(all_charsets[cs->number]);
        newcs->mbminlen= 1;
        newcs->mbmaxlen= 1;
        if (simple_cs_is_full(all_charsets[cs->number]))
        {
          all_charsets[cs->number]->state |= MY_CS_LOADED;
        }
        all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
        
        /*
          Check if case sensitive sort order: A < a < B.
          We need MY_CS_FLAG for regex library, and for
          case sensitivity flag for 5.0 client protocol,
          to support isCaseSensitive() method in JDBC driver 
        */
        if (sort_order && sort_order['A'] < sort_order['a'] &&
                          sort_order['a'] < sort_order['B'])
          all_charsets[cs->number]->state|= MY_CS_CSSORT; 

        if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number]))
          all_charsets[cs->number]->state|= MY_CS_PUREASCII;
        if (!my_charset_is_ascii_compatible(cs))
          all_charsets[cs->number]->state|= MY_CS_NONASCII;
      }
    }
    else
    {
      /*
        We need the below to make get_charset_name()
        and get_charset_number() working even if a
        character set has not been really incompiled.
        The above functions are used for example
        in error message compiler extra/comp_err.c.
        If a character set was compiled, this information
        will get lost and overwritten in add_compiled_collation().
      */
      CHARSET_INFO *dst= all_charsets[cs->number];
      dst->number= cs->number;
      if (cs->comment)
	if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
	  return MY_XML_ERROR;
      if (cs->csname)
        if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
	  return MY_XML_ERROR;
      if (cs->name)
	if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME))))
	  return MY_XML_ERROR;
    }
    cs->number= 0;
    cs->primary_number= 0;
    cs->binary_number= 0;
    cs->name= NULL;
    cs->state= 0;
    cs->sort_order= NULL;
    cs->state= 0;
  }
  return MY_XML_OK;
}
Exemplo n.º 23
0
/*
  system msync() only syncs mmap'ed area to fs cache.
  fsync() is required to really sync to disc
*/
int my_msync(int fd, void *addr, size_t len, int flags)
{
  msync(addr, len, flags);
  return my_sync(fd, MYF(0));
}
Exemplo n.º 24
0
/**
  Wrappers for memory functions my_malloc (and friends)
  with C-compatbile API without extra "myf" argument.
*/
static void *
my_once_alloc_c(size_t size)
{ return my_once_alloc(size, MYF(MY_WME)); }
Exemplo n.º 25
0
MY_DIR	*my_dir(const char *path, myf MyFlags)
{
  char          *buffer;
  MY_DIR        *result= 0;
  FILEINFO      finfo;
  DYNAMIC_ARRAY *dir_entries_storage;
  MEM_ROOT      *names_storage;
#ifdef __BORLANDC__
  struct ffblk       find;
#else
  struct _finddata_t find;
#endif
  ushort	mode;
  char		tmp_path[FN_REFLEN],*tmp_file,attrib;
#ifdef _WIN64
  __int64       handle;
#else
  long		handle;
#endif
  DBUG_ENTER("my_dir");
  DBUG_PRINT("my",("path: '%s' stat: %d  MyFlags: %d",path,MyFlags));

  /* Put LIB-CHAR as last path-character if not there */
  tmp_file=tmp_path;
  if (!*path)
    *tmp_file++ ='.';				/* From current dir */
  tmp_file= strnmov(tmp_file, path, FN_REFLEN-5);
  if (tmp_file[-1] == FN_DEVCHAR)
    *tmp_file++= '.';				/* From current dev-dir */
  if (tmp_file[-1] != FN_LIBCHAR)
    *tmp_file++ =FN_LIBCHAR;
  tmp_file[0]='*';				/* Windows needs this !??? */
  tmp_file[1]='.';
  tmp_file[2]='*';
  tmp_file[3]='\0';

  if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
                          ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
                          sizeof(MEM_ROOT), MyFlags)))
    goto error;

  dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); 
  names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
                             ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
  
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
  {
    my_free(buffer);
    goto error;
  }
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
  
  /* MY_DIR structure is allocated and completly initialized at this point */
  result= (MY_DIR*)buffer;

#ifdef __BORLANDC__
  if ((handle= findfirst(tmp_path,&find,0)) == -1L)
#else
  if ((handle=_findfirst(tmp_path,&find)) == -1L)
#endif
  {
    DBUG_PRINT("info", ("findfirst returned error, errno: %d", errno));
    if  (errno != EINVAL)
      goto error;
    /*
      Could not read the directory, no read access.
      Probably because by "chmod -r".
      continue and return zero files in dir
    */
  }
  else
  {

    do
    {
#ifdef __BORLANDC__
      attrib= find.ff_attrib;
#else
      attrib= find.attrib;
      /*
        Do not show hidden and system files which Windows sometimes create.
        Note. Because Borland's findfirst() is called with the third
        argument = 0 hidden/system files are excluded from the search.
      */
      if (attrib & (_A_HIDDEN | _A_SYSTEM))
        continue;
#endif
#ifdef __BORLANDC__
      if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
        goto error;
#else
      if (!(finfo.name= strdup_root(names_storage, find.name)))
        goto error;
#endif
      if (MyFlags & MY_WANT_STAT)
      {
        if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
                                                 sizeof(MY_STAT))))
          goto error;

        memset(finfo.mystat, 0, sizeof(MY_STAT));
#ifdef __BORLANDC__
        finfo.mystat->st_size=find.ff_fsize;
#else
        finfo.mystat->st_size=find.size;
#endif
        mode= MY_S_IREAD;
        if (!(attrib & _A_RDONLY))
          mode|= MY_S_IWRITE;
        if (attrib & _A_SUBDIR)
          mode|= MY_S_IFDIR;
        finfo.mystat->st_mode= mode;
#ifdef __BORLANDC__
        finfo.mystat->st_mtime= ((uint32) find.ff_ftime);
#else
        finfo.mystat->st_mtime= ((uint32) find.time_write);
#endif
      }
      else
        finfo.mystat= NULL;

      if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
        goto error;
    }
#ifdef __BORLANDC__
    while (findnext(&find) == 0);
#else
    while (_findnext(handle,&find) == 0);

    _findclose(handle);
#endif
  }

  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
  result->number_off_files= dir_entries_storage->elements;

  if (!(MyFlags & MY_DONT_SORT))
    my_qsort((void *) result->dir_entry, result->number_off_files,
          sizeof(FILEINFO), (qsort_cmp) comp_names);
  DBUG_PRINT("exit", ("found %d files", result->number_off_files));
  DBUG_RETURN(result);
error:
  my_errno=errno;
#ifndef __BORLANDC__
  if (handle != -1)
      _findclose(handle);
#endif
  my_dirend(result);
  if (MyFlags & MY_FAE+MY_WME)
  {
    char errbuf[MYSYS_STRERROR_SIZE];
    my_error(EE_DIR, MYF(ME_BELL+ME_WAITTANG), path,
             errno, my_strerror(errbuf, sizeof(errbuf), errno));
  }
  DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
Exemplo n.º 26
0
static void *
my_realloc_c(void *old, size_t size)
{ return my_realloc(key_memory_charset_loader,
                    old, size, MYF(MY_WME)); }
Exemplo n.º 27
0
int mrn_parse_table_param(MRN_SHARE *share, TABLE *table)
{
  int i, error = 0;
  int title_length;
  const char *sprit_ptr[2];
  const char *tmp_ptr, *start_ptr;
  char *params_string = NULL;
#ifdef WITH_PARTITION_STORAGE_ENGINE
  partition_element *part_elem;
  partition_element *sub_elem;
#endif
  MRN_DBUG_ENTER_FUNCTION();
#ifdef WITH_PARTITION_STORAGE_ENGINE
  mrn_get_partition_info(share->table_name, share->table_name_length, table,
    &part_elem, &sub_elem);
#endif
#ifdef WITH_PARTITION_STORAGE_ENGINE
  for (i = 4; i > 0; i--)
#else
  for (i = 2; i > 0; i--)
#endif
  {
    const char *params_string_value = NULL;
    uint params_string_length = 0;
    switch (i)
    {
#ifdef WITH_PARTITION_STORAGE_ENGINE
      case 4:
        if (!sub_elem || !sub_elem->part_comment)
          continue;
        DBUG_PRINT("info", ("mroonga create sub comment string"));
        params_string_value = sub_elem->part_comment;
        params_string_length = strlen(params_string_value);
        DBUG_PRINT("info",
                   ("mroonga sub comment string=%s", params_string_value));
        break;
      case 3:
        if (!part_elem || !part_elem->part_comment)
          continue;
        DBUG_PRINT("info", ("mroonga create part comment string"));
        params_string_value = part_elem->part_comment;
        params_string_length = strlen(params_string_value);
        DBUG_PRINT("info",
                   ("mroonga part comment string=%s", params_string_value));
        break;
#endif
      case 2:
        if (LEX_STRING_IS_EMPTY(table->s->comment))
          continue;
        DBUG_PRINT("info", ("mroonga create comment string"));
        params_string_value = table->s->comment.str;
        params_string_length = table->s->comment.length;
        DBUG_PRINT("info",
                   ("mroonga comment string=%.*s",
                    params_string_length, params_string_value));
        break;
      default:
        if (LEX_STRING_IS_EMPTY(table->s->connect_string))
          continue;
        DBUG_PRINT("info", ("mroonga create connect_string string"));
        params_string_value = table->s->connect_string.str;
        params_string_length = table->s->connect_string.length;
        DBUG_PRINT("info",
                   ("mroonga connect_string=%.*s",
                    params_string_length, params_string_value));
        break;
    }

    if (!params_string_value) {
      continue;
    }

    {
      params_string = mrn_my_strndup(params_string_value,
                                     params_string_length,
                                     MYF(MY_WME));
      if (!params_string) {
        error = HA_ERR_OUT_OF_MEM;
        goto error;
      }

      sprit_ptr[0] = params_string;
      while (sprit_ptr[0])
      {
        if ((sprit_ptr[1] = strchr(sprit_ptr[0], ',')))
        {
          sprit_ptr[1]++;
        }
        tmp_ptr = sprit_ptr[0];
        sprit_ptr[0] = sprit_ptr[1];
        while (*tmp_ptr == ' ' || *tmp_ptr == '\r' ||
               *tmp_ptr == '\n' || *tmp_ptr == '\t')
          tmp_ptr++;

        if (*tmp_ptr == '\0')
          continue;

        DBUG_PRINT("info", ("mroonga title_str=%s", tmp_ptr));
        title_length = 0;
        start_ptr = tmp_ptr;
        while (*start_ptr != ' ' && *start_ptr != '\'' &&
               *start_ptr != '"' && *start_ptr != '\0' &&
               *start_ptr != '\r' && *start_ptr != '\n' &&
               *start_ptr != '\t' && *start_ptr != ',')
        {
          title_length++;
          start_ptr++;
        }
        DBUG_PRINT("info", ("mroonga title_length=%u", title_length));

        switch (title_length)
        {
        case 6:
          MRN_PARAM_STR("engine", engine);
          break;
        case 10:
          MRN_PARAM_STR("normalizer", normalizer);
          break;
        case 13:
          MRN_PARAM_STR("token_filters", token_filters);
          break;
        case 17:
          MRN_PARAM_STR("default_tokenizer", default_tokenizer);
          break;
        default:
          break;
        }
      }

      my_free(params_string);
      params_string = NULL;
    }
  }

  if (!share->engine && mrn_default_wrapper_engine)
  {
    share->engine_length = strlen(mrn_default_wrapper_engine);
    if (
      !(share->engine = mrn_my_strndup(mrn_default_wrapper_engine,
                                       share->engine_length,
                                       MYF(MY_WME)))
    ) {
      error = HA_ERR_OUT_OF_MEM;
      goto error;
    }
  }

  if (share->engine)
  {
    LEX_STRING engine_name;
    if (
      (
        share->engine_length == MRN_DEFAULT_LEN &&
        !strncasecmp(share->engine, MRN_DEFAULT_STR, MRN_DEFAULT_LEN)
      ) ||
      (
        share->engine_length == MRN_GROONGA_LEN &&
        !strncasecmp(share->engine, MRN_GROONGA_STR, MRN_GROONGA_LEN)
      )
    ) {
      my_free(share->engine);
      share->engine = NULL;
      share->engine_length = 0;
    } else {
      engine_name.str = share->engine;
      engine_name.length = share->engine_length;
      if (!(share->plugin = MRN_HA_RESOLVE_BY_NAME(&engine_name)))
      {
        my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), share->engine);
        error = ER_UNKNOWN_STORAGE_ENGINE;
        goto error;
      }
      share->hton = MRN_PLUGIN_DATA(share->plugin, handlerton *);
      share->wrapper_mode = TRUE;
    }
  }
Exemplo n.º 28
0
MYRG_INFO *myrg_parent_open(const char *parent_name,
                            int (*callback)(void*, const char*),
                            void *callback_param)
{
  MYRG_INFO *UNINIT_VAR(m_info);
  int       rc;
  int       errpos;
  int       save_errno;
  int       insert_method;
  uint      length;
  uint      child_count;
  File      fd;
  IO_CACHE  file_cache;
  char      parent_name_buff[FN_REFLEN * 2];
  char      child_name_buff[FN_REFLEN];
  DBUG_ENTER("myrg_parent_open");

  rc= 1;
  errpos= 0;
  bzero((char*) &file_cache, sizeof(file_cache));

  /* Open MERGE meta file. */
  if ((fd= mysql_file_open(rg_key_file_MRG,
                           fn_format(parent_name_buff, parent_name,
                                     "", MYRG_NAME_EXT,
                                     MY_UNPACK_FILENAME|MY_APPEND_EXT),
                           O_RDONLY | O_SHARE, MYF(0))) < 0)
    goto err; /* purecov: inspected */
  errpos= 1;

  if (init_io_cache(&file_cache, fd, 4 * IO_SIZE, READ_CACHE, 0, 0,
                    MYF(MY_WME | MY_NABP)))
    goto err; /* purecov: inspected */
  errpos= 2;

  /* Count children. Determine insert method. */
  child_count= 0;
  insert_method= 0;
  while ((length= my_b_gets(&file_cache, child_name_buff, FN_REFLEN - 1)))
  {
    /* Remove line terminator. */
    if (child_name_buff[length - 1] == '\n')
      child_name_buff[--length]= '\0';

    /* Skip empty lines. */
    if (!child_name_buff[0])
      continue; /* purecov: inspected */

    /* Skip comments, but evaluate insert method. */
    if (child_name_buff[0] == '#')
    {
      if (!strncmp(child_name_buff + 1, "INSERT_METHOD=", 14))
      {
        /* Compare buffer with global methods list: merge_insert_method. */
        insert_method= find_type(child_name_buff + 15,
                                 &merge_insert_method, FIND_TYPE_BASIC);
      }
      continue;
    }

    /* Count the child. */
    child_count++;
  }

  /* Allocate MERGE parent table structure. */
  if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) +
                                       child_count * sizeof(MYRG_TABLE),
                                       MYF(MY_WME | MY_ZEROFILL))))
    goto err; /* purecov: inspected */
  errpos= 3;
  m_info->open_tables= (MYRG_TABLE*) (m_info + 1);
  m_info->tables= child_count;
  m_info->merge_insert_method= insert_method > 0 ? insert_method : 0;
  /* This works even if the table list is empty. */
  m_info->end_table= m_info->open_tables + child_count;
  if (!child_count)
  {
    /* Do not attach/detach an empty child list. */
    m_info->children_attached= TRUE;
  }

  /* Call callback for each child. */
  my_b_seek(&file_cache, 0);
  while ((length= my_b_gets(&file_cache, child_name_buff, FN_REFLEN - 1)))
  {
    /* Remove line terminator. */
    if (child_name_buff[length - 1] == '\n')
      child_name_buff[--length]= '\0';

    /* Skip empty lines and comments. */
    if (!child_name_buff[0] || (child_name_buff[0] == '#'))
      continue;

    DBUG_PRINT("info", ("child: '%s'", child_name_buff));

    /* Callback registers child with handler table. */
    if ((rc= (*callback)(callback_param, child_name_buff)))
      goto err; /* purecov: inspected */
  }

  end_io_cache(&file_cache);
  (void) mysql_file_close(fd, MYF(0));
  mysql_mutex_init(rg_key_mutex_MYRG_INFO_mutex,
                   &m_info->mutex, MY_MUTEX_INIT_FAST);

  m_info->open_list.data= (void*) m_info;
  mysql_mutex_lock(&THR_LOCK_open);
  myrg_open_list= list_add(myrg_open_list, &m_info->open_list);
  mysql_mutex_unlock(&THR_LOCK_open);

  DBUG_RETURN(m_info);

  /* purecov: begin inspected */
 err:
  save_errno= my_errno;
  switch (errpos) {
  case 3:
    my_free(m_info);
    /* Fall through */
  case 2:
    end_io_cache(&file_cache);
    /* Fall through */
  case 1:
    (void) mysql_file_close(fd, MYF(0));
  }
  my_errno= save_errno;
  DBUG_RETURN (NULL);
  /* purecov: end */
}
Exemplo n.º 29
0
int mrn_add_column_param(MRN_SHARE *share, Field *field, int i)
{
  int error;
  char *param_string = NULL;
  int title_length;
  char *sprit_ptr[2];
  char *tmp_ptr, *start_ptr;

  MRN_DBUG_ENTER_FUNCTION();

  if (share->wrapper_mode) {
    DBUG_RETURN(0);
  }

  DBUG_PRINT("info", ("mroonga create comment string"));
  if (
    !(param_string = mrn_my_strndup(field->comment.str,
                                    field->comment.length,
                                    MYF(MY_WME)))
  ) {
    error = HA_ERR_OUT_OF_MEM;
    goto error_alloc_param_string;
  }
  DBUG_PRINT("info", ("mroonga comment string=%s", param_string));

  sprit_ptr[0] = param_string;
  while (sprit_ptr[0])
  {
    if ((sprit_ptr[1] = strchr(sprit_ptr[0], ',')))
    {
      *sprit_ptr[1] = '\0';
      sprit_ptr[1]++;
    }
    tmp_ptr = sprit_ptr[0];
    sprit_ptr[0] = sprit_ptr[1];
    while (*tmp_ptr == ' ' || *tmp_ptr == '\r' ||
      *tmp_ptr == '\n' || *tmp_ptr == '\t')
      tmp_ptr++;

    if (*tmp_ptr == '\0')
      continue;

    title_length = 0;
    start_ptr = tmp_ptr;
    while (*start_ptr != ' ' && *start_ptr != '\'' &&
      *start_ptr != '"' && *start_ptr != '\0' &&
      *start_ptr != '\r' && *start_ptr != '\n' &&
      *start_ptr != '\t')
    {
      title_length++;
      start_ptr++;
    }

    switch (title_length)
    {
      case 4:
        MRN_PARAM_STR_LIST("type", col_type, i);
        break;
      case 5:
        MRN_PARAM_STR_LIST("flags", col_flags, i);
        break;
      case 12:
        MRN_PARAM_STR_LIST("groonga_type", col_type, i);
        break;
      default:
        break;
    }
  }

  if (param_string)
    my_free(param_string);
  DBUG_RETURN(0);

error:
  if (param_string)
    my_free(param_string);
error_alloc_param_string:
  DBUG_RETURN(error);
}
Exemplo n.º 30
0
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
	      uint columns, MI_COLUMNDEF *recinfo,
	      uint uniques, MI_UNIQUEDEF *uniquedefs,
	      MI_CREATE_INFO *ci,uint flags)
{
  register uint i,j;
  File UNINIT_VAR(dfile), UNINIT_VAR(file);
  int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
  myf create_flag;
  uint fields,length,max_key_length,packed,pointer,real_length_diff,
       key_length,info_length,key_segs,options,min_key_length_skip,
       base_pos,long_varchar_count,varchar_length,
       max_key_block_length,unique_key_parts,fulltext_keys,offset;
  uint aligned_key_start, block_length;
  ulong reclength, real_reclength,min_pack_length;
  char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
  ulong pack_reclength;
  ulonglong tot_length,max_rows, tmp;
  enum en_fieldtype type;
  MYISAM_SHARE share;
  MI_KEYDEF *keydef,tmp_keydef;
  MI_UNIQUEDEF *uniquedef;
  HA_KEYSEG *keyseg,tmp_keyseg;
  MI_COLUMNDEF *rec;
  ulong *rec_per_key_part;
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
  MI_CREATE_INFO tmp_create_info;
  DBUG_ENTER("mi_create");
  DBUG_PRINT("enter", ("keys: %u  columns: %u  uniques: %u  flags: %u",
                      keys, columns, uniques, flags));

  if (!ci)
  {
    bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
    ci=&tmp_create_info;
  }

  if (keys + uniques > MI_MAX_KEY || columns == 0)
  {
    DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
  }

  errpos=0;
  options=0;
  bzero((uchar*) &share,sizeof(share));

  if (flags & HA_DONT_TOUCH_DATA)
  {
    if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
      options=ci->old_options &
	(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
	 HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
	 HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
    else
      options=ci->old_options &
	(HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
  }

  if (ci->reloc_rows > ci->max_rows)
    ci->reloc_rows=ci->max_rows;		/* Check if wrong parameter */

  if (!(rec_per_key_part=
	(ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
			   MYF(MY_WME | MY_ZEROFILL))))
    DBUG_RETURN(my_errno);

	/* Start by checking fields and field-types used */

  reclength=varchar_length=long_varchar_count=packed=
    min_pack_length=pack_reclength=0;
  for (rec=recinfo, fields=0 ;
       fields != columns ;
       rec++,fields++)
  {
    reclength+=rec->length;
    if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL &&
	type != FIELD_CHECK)
    {
      packed++;
      if (type == FIELD_BLOB)
      {
	share.base.blobs++;
	if (pack_reclength != INT_MAX32)
	{
	  if (rec->length == 4+portable_sizeof_char_ptr)
	    pack_reclength= INT_MAX32;
	  else
	    pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
	}
      }
      else if (type == FIELD_SKIP_PRESPACE ||
	       type == FIELD_SKIP_ENDSPACE)
      {
	if (pack_reclength != INT_MAX32)
	  pack_reclength+= rec->length > 255 ? 2 : 1;
	min_pack_length++;
      }
      else if (type == FIELD_VARCHAR)
      {
	varchar_length+= rec->length-1;          /* Used for min_pack_length */
	packed--;
	pack_reclength++;
        min_pack_length++;
        /* We must test for 257 as length includes pack-length */
        if (test(rec->length >= 257))
	{
	  long_varchar_count++;
	  pack_reclength+= 2;			/* May be packed on 3 bytes */
	}
      }
      else if (type != FIELD_SKIP_ZERO)
      {
	min_pack_length+=rec->length;
	packed--;				/* Not a pack record type */
      }
    }
    else					/* FIELD_NORMAL */
      min_pack_length+=rec->length;
  }
  if ((packed & 7) == 1)
  {				/* Bad packing, try to remove a zero-field */
    while (rec != recinfo)
    {
      rec--;
      if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
      {
        /*
          NOTE1: here we change a field type FIELD_SKIP_ZERO ->
          FIELD_NORMAL
        */
	rec->type=(int) FIELD_NORMAL;
	packed--;
	min_pack_length++;
	break;
      }
    }
  }

  if (packed || (flags & HA_PACK_RECORD))
    options|=HA_OPTION_PACK_RECORD;	/* Must use packed records */
  /* We can't use checksum with static length rows */
  if (!(options & HA_OPTION_PACK_RECORD))
    options&= ~HA_OPTION_CHECKSUM;
  if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
    min_pack_length+= varchar_length;
  if (flags & HA_CREATE_TMP_TABLE)
  {
    options|= HA_OPTION_TMP_TABLE;
    create_mode|= O_EXCL | O_NOFOLLOW;
  }
  if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
  {
    options|= HA_OPTION_CHECKSUM;
    min_pack_length++;
  }
  if (flags & HA_CREATE_DELAY_KEY_WRITE)
    options|= HA_OPTION_DELAY_KEY_WRITE;
  if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
    options|= HA_OPTION_RELIES_ON_SQL_LAYER;

  packed=(packed+7)/8;
  if (pack_reclength != INT_MAX32)
    pack_reclength+= reclength+packed +
      test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_OPTION_PACK_RECORD));
  min_pack_length+=packed;

  if (!ci->data_file_length && ci->max_rows)
  {
    if (pack_reclength == INT_MAX32 ||
             (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
      ci->data_file_length= ~(ulonglong) 0;
    else
      ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
  }
  else if (!ci->max_rows)
    ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
					 ((options & HA_OPTION_PACK_RECORD) ?
					  3 : 0)));

  if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
    pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
  else
    pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
  if (!(max_rows=(ulonglong) ci->max_rows))
    max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);


  real_reclength=reclength;
  if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
  {
    if (reclength <= pointer)
      reclength=pointer+1;		/* reserve place for delete link */
  }
  else
    reclength+= long_varchar_count;	/* We need space for varchar! */

  max_key_length=0; tot_length=0 ; key_segs=0;
  fulltext_keys=0;
  max_key_block_length=0;
  share.state.rec_per_key_part=rec_per_key_part;
  share.state.key_root=key_root;
  share.state.key_del=key_del;
  if (uniques)
  {
    max_key_block_length= myisam_block_size;
    max_key_length=	  MI_UNIQUE_HASH_LENGTH + pointer;
  }

  for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
  {

    share.state.key_root[i]= HA_OFFSET_ERROR;
    min_key_length_skip=length=real_length_diff=0;
    key_length=pointer;
    if (keydef->flag & HA_SPATIAL)
    {
#ifdef HAVE_SPATIAL
      /* BAR TODO to support 3D and more dimensions in the future */
      uint sp_segs=SPDIMS*2;
      keydef->flag=HA_SPATIAL;

      if (flags & HA_DONT_TOUCH_DATA)
      {
        /*
           called by myisamchk - i.e. table structure was taken from
           MYI file and SPATIAL key *does have* additional sp_segs keysegs.
           keydef->seg here points right at the GEOMETRY segment,
           so we only need to decrease keydef->keysegs.
           (see recreate_table() in mi_check.c)
        */
        keydef->keysegs-=sp_segs-1;
      }

      for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
	   j++, keyseg++)
      {
        if (keyseg->type != HA_KEYTYPE_BINARY &&
	    keyseg->type != HA_KEYTYPE_VARBINARY1 &&
            keyseg->type != HA_KEYTYPE_VARBINARY2)
        {
          my_errno=HA_WRONG_CREATE_OPTION;
          goto err;
        }
      }
      keydef->keysegs+=sp_segs;
      key_length+=SPLEN*sp_segs;
      length++;                              /* At least one length byte */
      min_key_length_skip+=SPLEN*2*SPDIMS;
#else
      my_errno= HA_ERR_UNSUPPORTED;
      goto err;
#endif /*HAVE_SPATIAL*/
    }
    else if (keydef->flag & HA_FULLTEXT)
    {
      keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
      options|=HA_OPTION_PACK_KEYS;             /* Using packed keys */

      for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
	   j++, keyseg++)
      {
        if (keyseg->type != HA_KEYTYPE_TEXT &&
	    keyseg->type != HA_KEYTYPE_VARTEXT1 &&
            keyseg->type != HA_KEYTYPE_VARTEXT2)
        {
          my_errno=HA_WRONG_CREATE_OPTION;
          goto err;
        }
        if (!(keyseg->flag & HA_BLOB_PART) &&
	    (keyseg->type == HA_KEYTYPE_VARTEXT1 ||
             keyseg->type == HA_KEYTYPE_VARTEXT2))
        {
          /* Make a flag that this is a VARCHAR */
          keyseg->flag|= HA_VAR_LENGTH_PART;
          /* Store in bit_start number of bytes used to pack the length */
          keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)?
                              1 : 2);
        }
      }

      fulltext_keys++;
      key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
      length++;                              /* At least one length byte */
      min_key_length_skip+=HA_FT_MAXBYTELEN;
      real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
    }
    else
    {
      /* Test if prefix compression */
      if (keydef->flag & HA_PACK_KEY)
      {
	/* Can't use space_compression on number keys */
	if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
	    keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
	  keydef->seg[0].flag&= ~HA_SPACE_PACK;

	/* Only use HA_PACK_KEY when first segment is a variable length key */
	if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
				     HA_VAR_LENGTH_PART)))
	{
	  /* pack relative to previous key */
	  keydef->flag&= ~HA_PACK_KEY;
	  keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
	}
	else
	{
	  keydef->seg[0].flag|=HA_PACK_KEY;	/* for easyer intern test */
	  keydef->flag|=HA_VAR_LENGTH_KEY;
	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
	}
      }
      if (keydef->flag & HA_BINARY_PACK_KEY)
	options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */

      if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment)
	share.base.auto_key=i+1;
      for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++)
      {
	/* numbers are stored with high by first to make compression easier */
	switch (keyseg->type) {
	case HA_KEYTYPE_SHORT_INT:
	case HA_KEYTYPE_LONG_INT:
	case HA_KEYTYPE_FLOAT:
	case HA_KEYTYPE_DOUBLE:
	case HA_KEYTYPE_USHORT_INT:
	case HA_KEYTYPE_ULONG_INT:
	case HA_KEYTYPE_LONGLONG:
	case HA_KEYTYPE_ULONGLONG:
	case HA_KEYTYPE_INT24:
	case HA_KEYTYPE_UINT24:
	case HA_KEYTYPE_INT8:
	  keyseg->flag|= HA_SWAP_KEY;
          break;
        case HA_KEYTYPE_VARTEXT1:
        case HA_KEYTYPE_VARTEXT2:
        case HA_KEYTYPE_VARBINARY1:
        case HA_KEYTYPE_VARBINARY2:
          if (!(keyseg->flag & HA_BLOB_PART))
          {
            /* Make a flag that this is a VARCHAR */
            keyseg->flag|= HA_VAR_LENGTH_PART;
            /* Store in bit_start number of bytes used to pack the length */
            keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
                                 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
                                1 : 2);
          }
          break;
	default:
	  break;
	}
	if (keyseg->flag & HA_SPACE_PACK)
	{
          DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
	  keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
	  length++;				/* At least one length byte */
	  min_key_length_skip+=keyseg->length;
	  if (keyseg->length >= 255)
	  {					/* prefix may be 3 bytes */
	    min_key_length_skip+=2;
	    length+=2;
	  }
	}
	if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
	{
          DBUG_ASSERT(!test_all_bits(keyseg->flag,
                                    (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
	  keydef->flag|=HA_VAR_LENGTH_KEY;
	  length++;				/* At least one length byte */
	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
	  min_key_length_skip+=keyseg->length;
	  if (keyseg->length >= 255)
	  {					/* prefix may be 3 bytes */
	    min_key_length_skip+=2;
	    length+=2;
	  }
	}
	key_length+= keyseg->length;
	if (keyseg->null_bit)
	{
	  key_length++;
	  options|=HA_OPTION_PACK_KEYS;
	  keyseg->flag|=HA_NULL_PART;
	  keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
	}
      }
    } /* if HA_FULLTEXT */
    key_segs+=keydef->keysegs;
    if (keydef->keysegs > MI_MAX_KEY_SEG)
    {
      my_errno=HA_WRONG_CREATE_OPTION;
      goto err;
    }
    /*
      key_segs may be 0 in the case when we only want to be able to
      add on row into the table. This can happen with some DISTINCT queries
      in MySQL
    */
    if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
	key_segs)
      share.state.rec_per_key_part[key_segs-1]=1L;
    length+=key_length;
    /* Get block length for key, if defined by user */
    block_length= (keydef->block_length ? 
                   my_round_up_to_next_power(keydef->block_length) :
                   myisam_block_size);
    block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
    block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);

    keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
                                                 pointer,MI_MAX_KEYPTR_SIZE,
                                                 block_length);
    if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
        length >= MI_MAX_KEY_BUFF)
    {
      my_errno=HA_WRONG_CREATE_OPTION;
      goto err;
    }
    set_if_bigger(max_key_block_length,keydef->block_length);
    keydef->keylength= (uint16) key_length;
    keydef->minlength= (uint16) (length-min_key_length_skip);
    keydef->maxlength= (uint16) length;

    if (length > max_key_length)
      max_key_length= length;
    tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
				    (length*2)))*
      (ulong) keydef->block_length;
  }
  for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
    key_del[i]=HA_OFFSET_ERROR;

  unique_key_parts=0;
  offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
  for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
  {
    uniquedef->key=keys+i;
    unique_key_parts+=uniquedef->keysegs;
    share.state.key_root[keys+i]= HA_OFFSET_ERROR;
    tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
                         ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
                         (ulong) myisam_block_size;
  }
  keys+=uniques;				/* Each unique has 1 key */
  key_segs+=uniques;				/* Each unique has 1 key seg */

  base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
	    max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
	    MI_STATE_KEYBLOCK_SIZE+
	    key_segs*MI_STATE_KEYSEG_SIZE);
  info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
			       keys * MI_KEYDEF_SIZE+
			       uniques * MI_UNIQUEDEF_SIZE +
			       (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
			       columns*MI_COLUMNDEF_SIZE);
  DBUG_PRINT("info", ("info_length: %u", info_length));
  /* There are only 16 bits for the total header length. */
  if (info_length > 65535)
  {
    my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
                    "indexes and/or unique constraints.",
                    MYF(0), name + dirname_length(name));
    my_errno= HA_WRONG_CREATE_OPTION;
    goto err;
  }

  bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
  ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
			HA_OPTION_COMPRESS_RECORD |
			HA_OPTION_TEMP_COMPRESS_RECORD: 0);
  mi_int2store(share.state.header.options,ci->old_options);
  mi_int2store(share.state.header.header_length,info_length);
  mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
  mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
  mi_int2store(share.state.header.base_pos,base_pos);
  share.state.header.language= (ci->language ?
				ci->language : default_charset_info->number);
  share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;

  share.state.dellink = HA_OFFSET_ERROR;
  share.state.process=	(ulong) getpid();
  share.state.unique=	(ulong) 0;
  share.state.update_count=(ulong) 0;
  share.state.version=	(ulong) time((time_t*) 0);
  share.state.sortkey=  (ushort) ~0;
  share.state.auto_increment=ci->auto_increment;
  share.options=options;
  share.base.rec_reflength=pointer;
  /* Get estimate for index file length (this may be wrong for FT keys) */
  tmp= (tot_length + max_key_block_length * keys *
	MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
  /*
    use maximum of key_file_length we calculated and key_file_length value we
    got from MYI file header (see also myisampack.c:save_state)
  */
  share.base.key_reflength=
    mi_get_pointer_length(max(ci->key_file_length,tmp),3);
  share.base.keys= share.state.header.keys= keys;
  share.state.header.uniques= uniques;
  share.state.header.fulltext_keys= fulltext_keys;
  mi_int2store(share.state.header.key_parts,key_segs);
  mi_int2store(share.state.header.unique_key_parts,unique_key_parts);

  mi_set_all_keys_active(share.state.key_map, keys);
  aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
                                               max_key_block_length :
                                               myisam_block_size);

  share.base.keystart= share.state.state.key_file_length=
    MY_ALIGN(info_length, aligned_key_start);
  share.base.max_key_block_length=max_key_block_length;
  share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
  share.base.records=ci->max_rows;
  share.base.reloc=  ci->reloc_rows;
  share.base.reclength=real_reclength;
  share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
  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;

  /* max_data_file_length and max_key_file_length are recalculated on open */
  if (options & HA_OPTION_TMP_TABLE)
    share.base.max_data_file_length=(my_off_t) ci->data_file_length;

  share.base.min_block_length=
    (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
     ! share.base.blobs) ?
    max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
    MI_EXTEND_BLOCK_LENGTH;
  if (! (flags & HA_DONT_TOUCH_DATA))
    share.state.create_time= (long) time((time_t*) 0);

  mysql_mutex_lock(&THR_LOCK_myisam);

  /*
    NOTE: For test_if_reopen() we need a real path name. Hence we need
    MY_RETURN_REAL_PATH for every fn_format(filename, ...).
  */
  if (ci->index_file_name)
  {
    char *iext= strrchr(ci->index_file_name, '.');
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
    if (options & HA_OPTION_TMP_TABLE)
    {
      char *path;
      /* chop off the table name, tempory tables use generated name */
      if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
        *path= '\0';
      fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
                MY_REPLACE_DIR | MY_UNPACK_FILENAME |
                MY_RETURN_REAL_PATH | MY_APPEND_EXT);
    }
    else
    {
      fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
                MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
                (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
    }
    fn_format(linkname, name, "", MI_NAME_IEXT,
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
    linkname_ptr=linkname;
    /*
      Don't create the table if the link or file exists to ensure that one
      doesn't accidently destroy another table.
    */
    create_flag=0;
  }
  else
  {
    char *iext= strrchr(name, '.');
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
    fn_format(filename, name, "", MI_NAME_IEXT,
              MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
              (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
    linkname_ptr=0;
    /* Replace the current file */
    create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
  }

  /*
    If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
    but no entry is made in the table cache for them.
    A TRUNCATE command checks for the table in the cache only and could
    be fooled to believe, the table is not open.
    Pull the emergency brake in this situation. (Bug #8306)

    NOTE: The filename is compared against unique_file_name of every
    open table. Hence we need a real path here.
  */
  if (test_if_reopen(filename))
  {
    my_printf_error(0, "MyISAM table '%s' is in use "
                    "(most likely by a MERGE table). Try FLUSH TABLES.",
                    MYF(0), name + dirname_length(name));
    my_errno= HA_ERR_TABLE_EXIST;
    goto err;
  }

  if ((file= mysql_file_create_with_symlink(mi_key_file_kfile,
                                            linkname_ptr, filename, 0,
                                            create_mode,
                                            MYF(MY_WME | create_flag))) < 0)
    goto err;
  errpos=1;

  if (!(flags & HA_DONT_TOUCH_DATA))
  {
    {
      if (ci->data_file_name)
      {
        char *dext= strrchr(ci->data_file_name, '.');
        int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);

        if (options & HA_OPTION_TMP_TABLE)
        {
          char *path;
          /* chop off the table name, tempory tables use generated name */
          if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
            *path= '\0';
          fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
                    MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
        }
        else
        {
          fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
                    MY_UNPACK_FILENAME |
                    (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
        }

	fn_format(linkname, name, "",MI_NAME_DEXT,
	          MY_UNPACK_FILENAME | MY_APPEND_EXT);
	linkname_ptr=linkname;
	create_flag=0;
      }
      else
      {
	fn_format(filename,name,"", MI_NAME_DEXT,
	          MY_UNPACK_FILENAME | MY_APPEND_EXT);
	linkname_ptr=0;
        create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
      }
      if ((dfile=
           mysql_file_create_with_symlink(mi_key_file_dfile,
                                          linkname_ptr, filename, 0,
                                          create_mode,
                                          MYF(MY_WME | create_flag))) < 0)
	goto err;
    }
    errpos=3;
  }

  DBUG_PRINT("info", ("write state info and base info"));
  if (mi_state_info_write(file, &share.state, 2) ||
      mi_base_info_write(file, &share.base))
    goto err;
#ifndef DBUG_OFF
  if ((uint) mysql_file_tell(file, MYF(0)) != base_pos + MI_BASE_INFO_SIZE)
  {
    uint pos=(uint) mysql_file_tell(file, MYF(0));
    DBUG_PRINT("warning",("base_length: %d  != used_length: %d",
			  base_pos+ MI_BASE_INFO_SIZE, pos));
  }
#endif

  /* Write key and keyseg definitions */
  DBUG_PRINT("info", ("write key and keyseg definitions"));
  for (i=0 ; i < share.base.keys - uniques; i++)
  {
    uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;

    if (mi_keydef_write(file, &keydefs[i]))
      goto err;
    for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
      if (mi_keyseg_write(file, &keydefs[i].seg[j]))
       goto err;
#ifdef HAVE_SPATIAL
    for (j=0 ; j < sp_segs ; j++)
    {
      HA_KEYSEG sseg;
      sseg.type=SPTYPE;
      sseg.language= 7;                         /* Binary */
      sseg.null_bit=0;
      sseg.bit_start=0;
      sseg.bit_end=0;
      sseg.bit_length= 0;
      sseg.bit_pos= 0;
      sseg.length=SPLEN;
      sseg.null_pos=0;
      sseg.start=j*SPLEN;
      sseg.flag= HA_SWAP_KEY;
      if (mi_keyseg_write(file, &sseg))
        goto err;
    }
#endif
  }
  /* Create extra keys for unique definitions */
  offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
  bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
  bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
  for (i=0; i < uniques ; i++)
  {
    tmp_keydef.keysegs=1;
    tmp_keydef.flag=		HA_UNIQUE_CHECK;
    tmp_keydef.block_length=	(uint16)myisam_block_size;
    tmp_keydef.keylength=	MI_UNIQUE_HASH_LENGTH + pointer;
    tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
    tmp_keyseg.type=		MI_UNIQUE_HASH_TYPE;
    tmp_keyseg.length=		MI_UNIQUE_HASH_LENGTH;
    tmp_keyseg.start=		offset;
    offset+=			MI_UNIQUE_HASH_LENGTH;
    if (mi_keydef_write(file,&tmp_keydef) ||
	mi_keyseg_write(file,(&tmp_keyseg)))
      goto err;
  }

  /* Save unique definition */
  DBUG_PRINT("info", ("write unique definitions"));
  for (i=0 ; i < share.state.header.uniques ; i++)
  {
    HA_KEYSEG *keyseg_end;
    keyseg= uniquedefs[i].seg;
    if (mi_uniquedef_write(file, &uniquedefs[i]))
      goto err;
    for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
         keyseg < keyseg_end;
         keyseg++)
    {
      switch (keyseg->type) {
      case HA_KEYTYPE_VARTEXT1:
      case HA_KEYTYPE_VARTEXT2:
      case HA_KEYTYPE_VARBINARY1:
      case HA_KEYTYPE_VARBINARY2:
        if (!(keyseg->flag & HA_BLOB_PART))
        {
          keyseg->flag|= HA_VAR_LENGTH_PART;
          keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
                               keyseg->type == HA_KEYTYPE_VARBINARY1) ?
                              1 : 2);
        }
        break;
      default:
        break;
      }
      if (mi_keyseg_write(file, keyseg))
	goto err;
    }
  }
  DBUG_PRINT("info", ("write field definitions"));
  for (i=0 ; i < share.base.fields ; i++)
    if (mi_recinfo_write(file, &recinfo[i]))
      goto err;

#ifndef DBUG_OFF
  if ((uint) mysql_file_tell(file, MYF(0)) != info_length)
  {
    uint pos= (uint) mysql_file_tell(file, MYF(0));
    DBUG_PRINT("warning",("info_length: %d  != used_length: %d",
			  info_length, pos));
  }
#endif

	/* Enlarge files */
  DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
  if (mysql_file_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
    goto err;

  if (! (flags & HA_DONT_TOUCH_DATA))
  {
#ifdef USE_RELOC
    if (mysql_file_chsize(dfile, share.base.min_pack_length*ci->reloc_rows,
                          0, MYF(0)))
      goto err;
#endif
    errpos=2;
    if (mysql_file_close(dfile, MYF(0)))
      goto err;
  }
  errpos=0;
  mysql_mutex_unlock(&THR_LOCK_myisam);
  if (mysql_file_close(file, MYF(0)))
    goto err;
  my_free(rec_per_key_part);
  DBUG_RETURN(0);

err:
  mysql_mutex_unlock(&THR_LOCK_myisam);
  save_errno=my_errno;
  switch (errpos) {
  case 3:
    (void) mysql_file_close(dfile, MYF(0));
    /* fall through */
  case 2:
  if (! (flags & HA_DONT_TOUCH_DATA))
    mysql_file_delete_with_symlink(mi_key_file_dfile,
                                   fn_format(filename, name, "", MI_NAME_DEXT,
                                             MY_UNPACK_FILENAME | MY_APPEND_EXT),
                                   MYF(0));
    /* fall through */
  case 1:
    (void) mysql_file_close(file, MYF(0));
    if (! (flags & HA_DONT_TOUCH_DATA))
      mysql_file_delete_with_symlink(mi_key_file_kfile,
                                     fn_format(filename, name, "", MI_NAME_IEXT,
                                               MY_UNPACK_FILENAME | MY_APPEND_EXT),
                                     MYF(0));
  }
  my_free(rec_per_key_part);
  DBUG_RETURN(my_errno=save_errno);		/* return the fatal errno */
}