/* Copyright (C) 1979-1996 TcX AB & Monty Program KB & Detron HB This software is distributed with NO WARRANTY OF ANY KIND. No author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing. Refer to the Free Public License (the "License") for full details. Every copy of this file must include a copy of the License, normally in a plain ASCII text file named PUBLIC. The License grants you the right to copy, modify and redistribute this file, but only under certain conditions described in the License. Among other things, the License requires that the copyright notice and this notice be preserved on all copies. */ /* Diverse funktioner som anv{nds allt som oftast i datanet */ #include "mysql_priv.h" #include /* Functions defined in this file */ static void frm_error(int error,TABLE *form,const char *name,int errortype); static int read_string(File file, gptr *to, uint length); static void fix_type_pointers(my_string **array, TYPELIB *point_to_type, uint types, my_string *names); static uint find_field(TABLE *form,uint start,uint length); static byte* get_field_name(Field *buff,uint *length,my_bool not_used) { *length= strlen(buff->field_name); return (byte*) buff->field_name; } /* Open a .frm file */ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, TABLE *outparam) { reg1 uint i; reg2 uchar *strpos; int j,flag,funktpos,error; uint rec_buff_length,n_length,int_length,records,key_parts,keys, interval_count,interval_parts; ulong pos; char index_file[FN_REFLEN],*names; uchar head[288],*disk_buff,new_field_pack_flag; my_string record,keynames,*int_array; bool new_frm_ver,use_hash; File file; Field **field,*reg_field; KEY *keyinfo; KEY_PART_INFO *key_part; uchar *null_pos; uint null_bit; DBUG_ENTER("openfrm"); DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam)); bzero((char*) outparam,sizeof(*outparam)); disk_buff=NULL; record= NULL; keynames=NullS; outparam->db_stat = db_stat; funktpos=0; key_parts=0; init_sql_alloc(&outparam->mem_root,1024); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root); outparam->real_name=strdup_root(&outparam->mem_root, name+dirname_length(name)); *fn_ext(outparam->real_name)='\0'; // Remove extension outparam->table_name=my_strdup(alias,MYF(MY_WME)); flag= (prgflag & CHANGE_FRM) ? O_RDWR : O_RDONLY | O_SHARE; error=1; if ((file=my_open(fn_format(index_file,name,"",reg_ext,4),flag, MYF(0))) < 0) { goto err_end; /* purecov: inspected */ } error=4; if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err; if (head[0] != (uchar) 254 || head[1] != 1 || (head[2] != FRM_VER && head[2] != FRM_VER+1)) goto err; /* purecov: inspected */ new_field_pack_flag=head[27]; new_frm_ver= (head[2] == FRM_VER+1); error=3; if (!(pos=get_form_pos(file,head,NullS,(TYPELIB*) 0))) goto err; /* purecov: inspected */ *fn_ext(index_file)='\0'; // Remove .frm extension outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3)); outparam->db_create_options=uint2korr(head+30); outparam->db_record_offset=1; error=4; outparam->max_records=uint4korr(head+18); outparam->reloc=uint4korr(head+22); /* Read keyinformation */ VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0))); if (read_string(file,(gptr*) &disk_buff,(uint) uint2korr(head+28))) goto err; /* purecov: inspected */ outparam->keys=keys=disk_buff[0]; key_parts=disk_buff[1]; n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO); if (!(keyinfo = (KEY*) alloc_root(&outparam->mem_root, n_length+uint2korr(disk_buff+4)))) goto err; /* purecov: inspected */ bzero((char*) keyinfo,n_length); outparam->key_info=keyinfo; outparam->max_key_length=0; key_part= (KEY_PART_INFO*) (keyinfo+keys); strpos=disk_buff+6; for (i=0 ; i < keys ; i++, keyinfo++) { keyinfo->dupp_key= (uint) strpos[0]; keyinfo->key_length= (uint) uint2korr(strpos+1); keyinfo->key_parts= (uint) strpos[3]; strpos+=4; keyinfo->key_part= key_part; set_if_bigger(outparam->max_key_length,keyinfo->key_length); for (j=keyinfo->key_parts ; j-- ; key_part++) { key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK); key_part->offset= (uint) uint2korr(strpos+2)-1; key_part->key_type= (uint) uint2korr(strpos+5); key_part->field= (Field*) 0; // Will be fixed later if (new_frm_ver) { key_part->key_part_flag= *(strpos+4); key_part->length= (uint) uint2korr(strpos+7); strpos+=9; } else { key_part->length= *(strpos+4); key_part->key_part_flag=0; if (key_part->length > 128) { key_part->length&=127; /* purecov: inspected */ key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */ } strpos+=7; } } } VOID(strmov(keynames= (my_string) key_part,(my_string) strpos)); outparam->reclength = uint2korr((head+16)); if (*(head+26)) outparam->system=1; /* one-record-database */ error=2; if ((ha_open(outparam,index_file, (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), (db_stat & HA_WAIT_IF_LOCKED || specialflag & SPECIAL_WAIT_IF_LOCKED ? HA_OPEN_WAIT_IF_LOCKED : (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? HA_OPEN_ABORT_IF_LOCKED : HA_OPEN_IGNORE_IF_LOCKED)))) goto err; /* purecov: inspected */ error=4; funktpos=1; outparam->reginfo.lock_type= TL_UNLOCK; if (db_stat & HA_OPEN_KEYFILE || (prgflag & DELAYED_OPEN)) records=2; else records=1; if (prgflag & (READ_ALL+EXTRA_RECORD)) records++; rec_buff_length=ALIGN_SIZE(outparam->reclength+1); if (!(outparam->record[0]= (byte*) (record = (char *) alloc_root(&outparam->mem_root, rec_buff_length * records)))) goto err; /* purecov: inspected */ record[outparam->reclength]=0; // For purify and ->c_ptr() outparam->rec_buff_length=rec_buff_length; if (my_pread(file,(byte*) record,(uint) outparam->reclength, (ulong) (uint2korr(head+6)+uint2korr(head+14)), MYF(MY_NABP))) goto err; /* purecov: inspected */ for (i=0 ; i < records ; i++, record+=rec_buff_length) { outparam->record[i]=(byte*) record; if (i) memcpy(record,record-rec_buff_length,(uint) outparam->reclength); } if (records == 2) { /* fix for select */ outparam->record[2]=outparam->record[1]; if (db_stat & HA_READ_ONLY) outparam->record[1]=outparam->record[0]; /* purecov: inspected */ } VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err; outparam->fields= uint2korr(head+258); pos=uint2korr(head+260); /* Length of all screens */ n_length=uint2korr(head+268); interval_count=uint2korr(head+270); interval_parts=uint2korr(head+272); int_length=uint2korr(head+274); outparam->null_fields=uint2korr(head+282); VOID(my_seek(file,pos,MY_SEEK_CUR,MYF(0))); DBUG_PRINT("form",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length)); if (!(field = (Field **) alloc_root(&outparam->mem_root, (uint) ((outparam->fields+1)*sizeof(Field*)+ interval_count*sizeof(TYPELIB)+ (outparam->fields+interval_parts+ keys+3)*sizeof(my_string)+ (n_length+int_length))))) goto err; /* purecov: inspected */ outparam->field=field; if (read_string(file,(gptr*) &disk_buff,(uint) (outparam->fields*11))) goto err; /* purecov: inspected */ outparam->intervals= (TYPELIB*) (outparam->field+outparam->fields+1); int_array= (my_string*) (outparam->intervals+interval_count); names= (char*) (int_array+outparam->fields+interval_parts+keys+3); if (!interval_count) outparam->intervals=0; // For better debugging if (my_read(file, (byte*) names, (uint) (n_length+int_length),MYF(MY_NABP))) goto err; /* purecov: inspected */ fix_type_pointers(&int_array,&outparam->fieldnames,1,&names); fix_type_pointers(&int_array,outparam->intervals,interval_count, &names); if (keynames) fix_type_pointers(&int_array,&outparam->keynames,1,&keynames); VOID(my_close(file,MYF(MY_WME))); strpos= disk_buff; record=(char*) outparam->record[0]-1; /* Fieldstart = 1 */ outparam->null_flags=null_pos= (uchar*) (record+1+outparam->reclength-(outparam->null_fields+7)/8); null_bit=1; use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH; if (use_hash) use_hash= !hash_init(&outparam->name_hash, outparam->fields,0,0, (hash_get_key) get_field_name,0, HASH_CASE_INSENSITIVE); for (i=0 ; i < outparam->fields; i++, strpos+= 11, field++) { uint pack_flag= uint2korr(strpos+6); uint interval_nr= (uint) strpos[10]; *field=reg_field=make_field(record+uint2korr(strpos+4), (uint32) strpos[3], // field_length null_pos,null_bit, pack_flag, (Field::utype) MTYP_TYPENR((uint) strpos[8]), (interval_nr ? outparam->intervals+interval_nr-1 : (TYPELIB*) 0), outparam->fieldnames.type_names[i], outparam); if (!(reg_field->flags & NOT_NULL_FLAG)) { if ((null_bit<<=1) == 256) { null_pos++; null_bit=1; } } if (reg_field->unireg_check == Field::NEXT_NUMBER) { if ((int) (outparam->next_number_index= (uint) find_ref_key(outparam,reg_field)) < 0) reg_field->unireg_check=Field::NONE; /* purecov: inspected */ else { outparam->found_next_number_field=reg_field; reg_field->flags|=AUTO_INCREMENT_FLAG; } } if (use_hash) (void) hash_insert(&outparam->name_hash,(byte*) *field); // Will never fail } outparam->key_parts=key_parts; *field=0; // End marker /* Fix key->name and key_part->field */ if (key_parts) { uint primary_key=(uint) (find_type("PRIMARY",&outparam->keynames,3)-1); uint ha_option=ha_option_flag[outparam->db_type]; keyinfo=outparam->key_info; key_part=keyinfo->key_part; for (uint key=0 ; key < outparam->keys ; key++,keyinfo++) { uint usable_parts=0; keyinfo->name=outparam->keynames.type_names[key]; if (primary_key >= MAX_KEY && !keyinfo->dupp_key) primary_key=key; for (i=0 ; i < keyinfo->key_parts ; key_part++,i++) { if (new_field_pack_flag <= 1) key_part->fieldnr=(uint16) find_field(outparam, (uint) key_part->offset, (uint) key_part->length); if (key_part->fieldnr) { // Should always be true ! key_part->field=outparam->field[key_part->fieldnr-1]; if (i == 0 && key != primary_key) key_part->field->flags |= (!keyinfo->dupp_key && key_part->field->pack_length() == keyinfo->key_length ? UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG); if (i == 0) key_part->field->key_start|= ((key_map) 1 << key); if (ha_option & HA_HAVE_KEYREAD_ONLY && key_part->field->pack_length() == key_part->length) { if (key_part->field->key_type() != HA_KEYTYPE_TEXT || !(ha_option & HA_KEYREAD_WRONG_STR)) key_part->field->part_of_key|= ((key_map) 1 << key); } if (!key_part->key_part_flag && usable_parts == i) usable_parts++; // For FILESORT key_part->field->flags|= PART_KEY_FLAG; if (key == primary_key) key_part->field->flags|= PRI_KEY_FLAG; if (key_part->field->pack_length() != key_part->length) { // Create a new field key_part->field=key_part->field->new_field(outparam); key_part->field->field_length=key_part->length; } } else { // Error: shorten key keyinfo->key_parts=usable_parts; keyinfo->dupp_key=0; } } keyinfo->usable_key_parts=usable_parts; // Filesort } } x_free((gptr) disk_buff); if (new_field_pack_flag <= 1) { /* Old file format with default null */ uint null_length=(outparam->null_fields+7)/8; bfill(outparam->null_flags,null_length,255); bfill(outparam->null_flags+outparam->rec_buff_length,null_length,255); if (records > 2) bfill(outparam->null_flags+outparam->rec_buff_length*2,null_length,255); } my_pthread_setspecific_ptr(THR_MALLOC,old_root); opened_tables++; #ifndef DBUG_OFF if (use_hash) (void) hash_check(&outparam->name_hash); #endif DBUG_RETURN (0); err: if (funktpos) { VOID(ha_close(outparam)); outparam->file=0; // For easyer errorchecking outparam->fields=0; // Probably safe } x_free((gptr) disk_buff); VOID(my_close(file,MYF(MY_WME))); err_end: /* Here when no file */ my_pthread_setspecific_ptr(THR_MALLOC,old_root); frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG); free_root(&outparam->mem_root); my_free(outparam->table_name,MYF(0)); DBUG_RETURN (error); } /* openfrm */ /* close a .frm file and it's tables*/ int closefrm(register TABLE *table) { int error=0; DBUG_ENTER("closefrm"); if (table->db_stat) error=ha_close(table); #ifdef NOT_USED // For old DIAB ISAM else if (table->dfile) error=my_close(table->dfile,MYF(MY_WME)); /* purecov: deadcode */ #endif if (table->table_name) { my_free(table->table_name,MYF(0)); table->table_name=0; } if (table->fields) { for (Field **ptr=table->field ; *ptr ; ptr++) delete *ptr; table->fields=0; } free_root(&table->mem_root); hash_free(&table->name_hash); table->file=0; /* For easyer errorchecking */ DBUG_RETURN(error); } /* Deallocte temporary blob storage */ void free_blobs(register TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { if ((*ptr)->flags & BLOB_FLAG) ((Field_blob *) (*ptr))->free(); } } /* Find where a form starts */ /* if formname is NullS then only formnames is read */ ulong get_form_pos(File file, uchar *head, my_string outname, TYPELIB *save_names) { uint a_length,names,length; uchar *pos,*buf; ulong ret_value=0; DBUG_ENTER("get_form_pos"); names=uint2korr(head+8); a_length=(names+2)*sizeof(my_string); /* Room for two extra */ if (!save_names) a_length=0; else save_names->type_names=0; /* Clear if error */ if (outname && head[32]) VOID(strmake((char*) outname,(char*) head+32,32)); if (names) { length=uint2korr(head+4); VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0))); if (!(buf= (uchar*) my_malloc((uint) length+a_length+names*4, MYF(MY_WME))) || my_read(file,(byte*) buf+a_length,(uint) (length+names*4), MYF(MY_NABP))) { /* purecov: inspected */ x_free((gptr) buf); /* purecov: inspected */ DBUG_RETURN(0L); /* purecov: inspected */ } pos= buf+a_length+length; ret_value=uint4korr(pos); } if (! save_names) my_free((gptr) buf,MYF(0)); else if (!names) bzero((char*) save_names,sizeof(save_names)); else { char *str; str=(my_string) (buf+a_length); fix_type_pointers((my_string**) &buf,save_names,1,&str); } DBUG_RETURN(ret_value); } /* Read string from a file with malloc */ static int read_string(File file, gptr *to, uint length) { DBUG_ENTER("read_string"); x_free((gptr) *to); if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) || my_read(file,(byte*) *to,length,MYF(MY_NABP))) { x_free((gptr) *to); /* purecov: inspected */ *to= 0; /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } *((char*) *to+length)= '\0'; DBUG_RETURN (0); } /* read_string */ /* Add a new form to a form file */ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, my_string newname) { uint i,bufflength,maxlength,n_length,length,names; ulong endpos,newpos; char buff[IO_SIZE]; uchar *pos; DBUG_ENTER("make_new_entry"); length=strlen(newname)+1; n_length=uint2korr(fileinfo+4); maxlength=uint2korr(fileinfo+6); names=uint2korr(fileinfo+8); newpos=uint4korr(fileinfo+10); if (64+length+n_length+(names+1)*4 > maxlength) { /* Expand file */ newpos+=IO_SIZE; int4store(fileinfo+10,newpos); endpos=my_seek(file,0L,MY_SEEK_END,MYF(0)); /* Copy from file-end */ bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */ while (endpos > maxlength) { VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0))); if (my_read(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET, MYF(0))); if ((my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))) DBUG_RETURN(0); endpos-=bufflength; bufflength=IO_SIZE; } bzero(buff,IO_SIZE); /* Null new block */ VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0))); if (my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); maxlength+=IO_SIZE; /* Fix old ref */ int2store(fileinfo+6,maxlength); for (i=names, pos= (uchar*) *formnames->type_names+n_length-1; i-- ; pos+=4) { endpos=uint4korr(pos)+IO_SIZE; int4store(pos,endpos); } } if (n_length == 1 ) { /* First name */ length++; VOID(strxmov(buff,"/",newname,"/",NullS)); } else VOID(strxmov(buff,newname,"/",NullS)); /* purecov: inspected */ VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0))); if (my_write(file,(byte*) buff,(uint) length+1,MYF(MY_NABP+MY_WME)) || (names && my_write(file,(byte*) (*formnames->type_names+n_length-1), names*4, MYF(MY_NABP+MY_WME))) || my_write(file,(byte*) fileinfo+10,(uint) 4,MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); /* purecov: inspected */ int2store(fileinfo+8,names+1); int2store(fileinfo+4,n_length+length); VOID(my_chsize(file,newpos,MYF(MY_WME))); /* Append file with '\0' */ DBUG_RETURN(newpos); } /* make_new_entry */ /* error message when opening a form file */ static void frm_error(int error, TABLE *form, const char *name, myf errortype) { int er_no; char buff[FN_REFLEN],*form_dev="",*datext; DBUG_ENTER("frm_error"); switch (error) { case 1: if (my_errno == ENOENT) { char *db; uint length=dirname_part(buff,name); buff[length-1]=0; db=buff+dirname_length(buff); my_error(ER_NO_SUCH_TABLE,MYF(0),db,form->real_name); } else my_error(ER_FILE_NOT_FOUND,errortype, fn_format(buff,name,form_dev,reg_ext,0),my_errno); break; case 2: { datext=bas_ext[form->db_type][test(form->db_stat & HA_OPEN_KEYFILE)]; er_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ? ER_FILE_USED : ER_CANT_OPEN_FILE; my_error(er_no,errortype, fn_format(buff,form->real_name,form_dev,datext,2),my_errno); break; } default: /* Better wrong error than none */ case 4: my_error(ER_NOT_FORM_FILE,errortype, fn_format(buff,name,form_dev,reg_ext,0)); break; } DBUG_VOID_RETURN; } /* frm_error */ /* ** fix a str_type to a array type ** typeparts sepearated with some char. differents types are separated ** with a '\0' */ static void fix_type_pointers(my_string **array, TYPELIB *point_to_type, uint types, my_string *names) { my_string type_name,ptr; char chr; ptr= *names; while (types--) { point_to_type->name=0; point_to_type->type_names= *array; if ((chr= *ptr)) /* Test if empty type */ { while ((type_name=strchr(ptr+1,chr)) != NullS) { *((*array)++) = ptr+1; *type_name= '\0'; /* End string */ ptr=type_name; } ptr+=2; /* Skipp end mark and last 0 */ } else ptr++; point_to_type->count= (uint) (*array - point_to_type->type_names); point_to_type++; *((*array)++)= NullS; /* End of type */ } *names=ptr; /* Update end */ return; } /* fix_type_pointers */ TYPELIB *typelib(List &strings) { TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB)); result->count=strings.elements; result->name=""; result->type_names=(my_string*) sql_alloc(sizeof(my_string**)*(result->count+1)); List_iterator it(strings); String *tmp; for (uint i=0; (tmp=it++) ; i++) result->type_names[i]=(char*) tmp->ptr(); result->type_names[result->count]=0; // End marker return result; } /* ** Search after a field with given start & length ** If an exact field isn't found, return longest field with starts ** at right position. ** Return 0 on error, else field number+1 ** This is needed because in some .frm fields 'fieldnr' was saved wrong */ static uint find_field(TABLE *form,uint start,uint length) { Field **field; uint i,pos; pos=0; for (field=form->field, i=1 ; i<= form->fields ; i++,field++) { if ((*field)->offset() == start) { if ((*field)->pack_length() == length) return (i); if (!pos || form->field[pos-1]->pack_length() < (*field)->pack_length()) pos=i; } } return (pos); } /* Kontrollerar att integern passar inom gr{nserna */ int set_zone(register int nr, int min_zone, int max_zone) { if (nr<=min_zone) return (min_zone); if (nr>=max_zone) return (max_zone); return (nr); } /* set_zone */ /* Justerar ett tal till n{sta j{mna diskbuffer */ ulong next_io_size(register ulong pos) { reg2 ulong offset; if ((offset= pos & (IO_SIZE-1))) return pos-offset+IO_SIZE; return pos; } /* next_io_size */ void append_unescaped(String *res,const char *pos) { for ( ; *pos ; pos++) { switch (*pos) { case 0: /* Must be escaped for 'mysql' */ res->append('\\'); res->append('0'); break; case '\n': /* Must be escaped for logs */ res->append('\\'); res->append('n'); break; case '\r': res->append('\\'); /* This gives better readbility */ res->append('r'); break; case '\\': res->append('\\'); /* Because of the sql syntax */ res->append('\\'); break; case '\'': res->append('\''); /* Because of the sql syntax */ res->append('\''); break; default: res->append(*pos); break; } } } /* Create a .frm file */ File create_frm(register my_string name, uint reclength, uchar *fileinfo, enum db_type database, uint options, ulong records, ulong reloc,uint keys) { register File file; uint key_length; ulong length; char fill[IO_SIZE]; if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { bzero((char*) fileinfo,64); fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+1; // Header fileinfo[3]= (uchar) ha_checktype(database); fileinfo[4]=1; int2store(fileinfo+6,IO_SIZE); /* Next block starts here */ key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16; length=(ulong) next_io_size((ulong) (IO_SIZE+key_length+reclength)); int4store(fileinfo+10,length); int2store(fileinfo+14,key_length); int2store(fileinfo+16,reclength); int4store(fileinfo+18,records); int4store(fileinfo+22,reloc); fileinfo[27]=2; /* Use long pack-fields */ int2store(fileinfo+30,options); VOID(fn_format((char*) fileinfo+32,name,"","",3)); bzero(fill,IO_SIZE); for (; length > IO_SIZE ; length-= IO_SIZE) { if (my_write(file,(byte*) fill,IO_SIZE,MYF(MY_WME | MY_NABP))) { VOID(my_close(file,MYF(0))); VOID(my_delete(name,MYF(0))); return(-1); } } } return (file); } /* create_frm */ int rename_file_ext(const char * from,const char * to,const char * ext) { char from_b[FN_REFLEN],to_b[FN_REFLEN]; VOID(strxmov(from_b,from,ext,NullS)); VOID(strxmov(to_b,to,ext,NullS)); return (my_rename(from_b,to_b,MYF(MY_WME))); } /* ** Change the current ref in the .frm file to the current file name */ int fix_frm_ref(const char * name) { char buff[FN_REFLEN]; int error= -1; uint length; File file; DBUG_ENTER("fix_frm_ref"); if ((file=my_open(fn_format(buff,name,"",reg_ext,2+4),O_RDWR,MYF_RW)) >= 0) { if (!(my_pread(file,(byte*) buff,32,32,MYF_RW | MY_WME))) { bzero(buff+32,32); /* Remove old name */ length=dirname_length(name); if (strlen(name)-length < 32) strmov(buff,name+length); if (!my_pwrite(file,(byte*) buff,32,32,MYF_RW | MY_WME)) error=0; } VOID(my_close(file,MYF(MY_WME))); } DBUG_RETURN(error); } /* Alloc a value as a string and return it If field is empty, return NULL */ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr) { Field *field=table->field[fieldnr]; char buff[MAX_FIELD_WIDTH]; String str(buff,sizeof(buff)); field->val_str(&str,&str); uint length=str.length(); if (!length) return NullS; char *to=alloc_root(mem,length+1); memcpy(to,str.ptr(),(uint) length); to[length]=0; return to; } /***************************************************************************** ** Instansiate templates *****************************************************************************/ #ifdef __GNUC__ template class List; template class List_iterator; #endif