int my_rename(const char *from, const char *to, myf MyFlags) { int error = 0; DBUG_ENTER("my_rename"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); #if defined(HAVE_FILE_VERSIONS) { /* Check that there isn't a old file */ int save_errno; MY_STAT my_stat_result; save_errno=my_errno; if (my_stat(to,&my_stat_result,MYF(0))) { my_errno=EEXIST; error= -1; if (MyFlags & MY_FAE+MY_WME) { char errbuf[MYSYS_STRERROR_SIZE]; my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG), from, to, my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno)); } DBUG_RETURN(error); } my_errno=save_errno; } #endif #if defined(__WIN__) if(!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED| MOVEFILE_REPLACE_EXISTING)) { my_osmaperr(GetLastError()); #else if (rename(from,to)) { #endif my_errno=errno; error = -1; if (MyFlags & (MY_FAE+MY_WME)) { char errbuf[MYSYS_STRERROR_SIZE]; my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG), from, to, my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno)); } } else if (MyFlags & MY_SYNC_DIR) { #ifdef NEED_EXPLICIT_SYNC_DIR /* do only the needed amount of syncs: */ char dir_from[FN_REFLEN], dir_to[FN_REFLEN]; size_t dir_from_length, dir_to_length; dirname_part(dir_from, from, &dir_from_length); dirname_part(dir_to, to, &dir_to_length); if (my_sync_dir(dir_from, MyFlags) || (strcmp(dir_from, dir_to) && my_sync_dir(dir_to, MyFlags))) error= -1; #endif } DBUG_RETURN(error); } /* my_rename */
int my_rename(const char *from, const char *to, myf MyFlags) { int error = 0; DBUG_ENTER("my_rename"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); #if defined(HAVE_FILE_VERSIONS) { /* Check that there isn't a old file */ int save_errno; MY_STAT my_stat_result; save_errno=my_errno; if (my_stat(to,&my_stat_result,MYF(0))) { my_errno=EEXIST; error= -1; if (MyFlags & MY_FAE+MY_WME) my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); DBUG_RETURN(error); } my_errno=save_errno; } #endif #if defined(HAVE_RENAME) #if defined(__WIN__) /* On windows we can't rename over an existing file: Remove any conflicting files: */ (void) my_delete(to, MYF(0)); #endif if (rename(from,to)) #else if (link(from, to) || unlink(from)) #endif { my_errno=errno; error = -1; if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); } else if (MyFlags & MY_SYNC_DIR) { #ifdef NEED_EXPLICIT_SYNC_DIR /* do only the needed amount of syncs: */ char dir_from[FN_REFLEN], dir_to[FN_REFLEN]; size_t dir_from_length, dir_to_length; dirname_part(dir_from, from, &dir_from_length); dirname_part(dir_to, to, &dir_to_length); if (my_sync_dir(dir_from, MyFlags) || (strcmp(dir_from, dir_to) && my_sync_dir(dir_to, MyFlags))) error= -1; #endif } DBUG_RETURN(error); } /* my_rename */
my_string fn_same(char *to, const char *name, int flag) { char dev[FN_REFLEN]; const char *ext; DBUG_ENTER("fn_same"); DBUG_PRINT("enter",("to: %s name: %s flag: %d",to,name,flag)); if ((ext=strrchr(name+dirname_part(dev,name),FN_EXTCHAR)) == 0) ext=""; DBUG_RETURN(fn_format(to,to,dev,ext,flag)); } /* fn_same */
char * my_path(char * to, const char *progname, const char *own_pathname_part) { char *start, *end, *prog; size_t to_length; DBUG_ENTER("my_path"); start=to; /* Return this */ if (progname && (dirname_part(to, progname, &to_length) || find_file_in_path(to,progname) || ((prog=getenv("_")) != 0 && dirname_part(to, prog, &to_length)))) { (void) intern_filename(to,to); if (!test_if_hard_path(to)) { if (!my_getwd(curr_dir,FN_REFLEN,MYF(0))) bchange((uchar*) to, 0, (uchar*) curr_dir, strlen(curr_dir), strlen(to)+1); } } else { if ((end = getenv("MY_BASEDIR_VERSION")) == 0 && (end = getenv("MY_BASEDIR")) == 0) { #ifdef DEFAULT_BASEDIR end= (char*) DEFAULT_BASEDIR; #else end= (char*) "/my/"; #endif } (void) intern_filename(to,end); to=strend(to); if (to != start && to[-1] != FN_LIBCHAR) *to++ = FN_LIBCHAR; (void) strmov(to,own_pathname_part); } DBUG_PRINT("exit",("to: '%s'",start)); DBUG_RETURN(start); } /* my_path */
char *intern_filename(char *to, const char *from) { size_t length, to_length; char buff[FN_REFLEN]; if (from == to) { /* Dirname may destroy from */ strmov(buff,from); from=buff; } length= dirname_part(to, from, &to_length); /* Copy dirname & fix chars */ (void) strmov(to + to_length,from+length); return (to); } /* intern_filename */
my_string unpack_filename(my_string to, const char *from) { uint length,n_length; char buff[FN_REFLEN]; DBUG_ENTER("unpack_filename"); length=dirname_part(buff,from); /* copy & convert dirname */ n_length=unpack_dirname(buff,buff); if (n_length+strlen(from+length) < FN_REFLEN) { (void) strmov(buff+n_length,from+length); (void) system_filename(to,buff); /* Fix to usably filename */ } else (void) system_filename(to,from); /* Fix to usably filename */ DBUG_RETURN(to); } /* unpack_filename */
size_t unpack_filename(char * to, const char *from) { size_t length, n_length, buff_length; char buff[FN_REFLEN + 1]; DBUG_ENTER("unpack_filename"); length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */ n_length=unpack_dirname(buff,buff); if (n_length+strlen(from+length) < FN_REFLEN) { (void) strmov(buff+n_length,from+length); length= system_filename(to,buff); /* Fix to usably filename */ } else length= system_filename(to,from); /* Fix to usably filename */ DBUG_RETURN(length); } /* unpack_filename */
my_string fn_ext(const char *name) { register my_string pos,gpos; DBUG_ENTER("fn_ext"); DBUG_PRINT("mfunkt",("name: '%s'",name)); #if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) { char buff[FN_REFLEN]; gpos=(my_string) name+dirname_part(buff,(char*) name); } #else if (!(gpos=strrchr(name,FNLIBCHAR))) gpos=name; #endif pos=strchr(gpos,FN_EXTCHAR); DBUG_RETURN (pos ? pos : strend(gpos)); } /* fn_ext */
char *fn_ext(const char *name) { register const char *pos, *gpos; DBUG_ENTER("fn_ext"); DBUG_PRINT("mfunkt",("name: '%s'",name)); #if defined(FN_DEVCHAR) || defined(BASKSLASH_MBTAIL) { char buff[FN_REFLEN]; size_t res_length; gpos= name+ dirname_part(buff,(char*) name, &res_length); } #else if (!(gpos= strrchr(name, FN_LIBCHAR))) gpos= name; #endif pos=strchr(gpos,FN_EXTCHAR); DBUG_RETURN((char*) (pos ? pos : strend(gpos))); } /* fn_ext */
my_string intern_filename(my_string to, const char *from) { #ifndef VMS { uint length; char buff[FN_REFLEN]; if (from == to) { /* Dirname may destroy from */ strmov(buff,from); from=buff; } length=dirname_part(to,from); /* Copy dirname & fix chars */ (void) strcat(to,from+length); return (to); } #else /* VMS */ /* change 'dev:[lib]xxx' to 'dev:lib/xxx' */ /* change 'dev:xxx' to 'dev:xxx' */ /* change 'dev:x/y/[.lib]' to 'dev:x/y/lib/ */ /* change '[.lib]' to './lib/' */ /* change '[x.y]' or '[x.][y]' or '[x][.y]' to '/x/y/' */ /* change '[000000.x] or [x.000000]' to '/x/' */ int par_length,root_length; my_string pos,from_pos,to_pos,end_pos; char buff[FN_REFLEN]; convert_dirname(buff,from,NullS); /* change '<>' to '[]' */ from_pos=buff; if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */ { pos++; to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos)); from_pos=pos; } else to_pos=to; root_length=strlen(FN_C_ROOT_DIR); if ((pos = strchr(from_pos,FN_C_BEFORE_DIR)) && (end_pos = strrchr(pos+1,FN_C_AFTER_DIR))) { to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos)); /* Copy all between ':' and '[' */ from_pos=pos+1; if (strinstr(from_pos,FN_C_ROOT_DIR) == 1 && (from_pos[root_length] == FN_C_DIR_SEP || from_pos[root_length] == FN_C_AFTER_DIR)) { from_pos+=root_length+1; } else if (*from_pos == FN_C_DIR_SEP) *(to_pos++) = FN_CURLIB; /* Set ./ first */ *(to_pos++) = FN_LIBCHAR; par_length=strlen(FN_C_PARENT_DIR); pos=to_pos; for (; from_pos <= end_pos ; from_pos++) { switch (*from_pos) { case FN_C_DIR_SEP: case FN_C_AFTER_DIR: if (pos != to_pos) { if ((int) (to_pos-pos) == root_length && is_suffix(pos,FN_C_ROOT_DIR)) to_pos=pos; /* remove root-pos */ else { *(to_pos++)=FN_LIBCHAR; /* Find lib */ pos=to_pos; } } break; case FN_C_BEFORE_DIR: break; case '-': /* *(FN_C_PARENT_DIR): */ if (to_pos[-1] == FN_LIBCHAR && strncmp(from_pos,FN_C_PARENT_DIR,par_length) == 0) { /* Change '-' to '..' */ to_pos=strmov(to_pos,FN_PARENTDIR); *(to_pos++)=FN_LIBCHAR; pos=to_pos; from_pos+=par_length-1; break; } /* Fall through */ default: *(to_pos++)= *from_pos; break; } } } (void) strmov(to_pos,from_pos); return (to); #endif /* VMS */ } /* intern_filename */
char * fn_format(char * to, const char *name, const char *dir, const char *extension, uint flag) { char dev[FN_REFLEN], buff[FN_REFLEN], *pos, *startpos; const char *ext; reg1 size_t length; size_t dev_length; my_bool not_used; DBUG_ENTER("fn_format"); DBUG_ASSERT(name != NULL); DBUG_ASSERT(extension != NULL); DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d", name,dir,extension,flag)); /* Copy and skip directory */ name+=(length=dirname_part(dev, (startpos=(char *) name), &dev_length)); if (length == 0 || (flag & MY_REPLACE_DIR)) { DBUG_ASSERT(dir != NULL); /* Use given directory */ convert_dirname(dev,dir,NullS); /* Fix to this OS */ } else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(dev)) { DBUG_ASSERT(dir != NULL); /* Put 'dir' before the given path */ strmake(buff,dev,sizeof(buff)-1); pos=convert_dirname(dev,dir,NullS); strmake(pos,buff,sizeof(buff)-1- (int) (pos-dev)); } if (flag & MY_PACK_FILENAME) pack_dirname(dev,dev); /* Put in ./.. and ~/.. */ if (flag & MY_UNPACK_FILENAME) (void) unpack_dirname(dev, dev, ¬_used); /* Replace ~/.. with dir */ if (!(flag & MY_APPEND_EXT) && (pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) { if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */ { length=strlength(name); /* Use old extension */ ext = ""; } else { length= (size_t) (pos-(char*) name); /* Change extension */ ext= extension; } } else { length=strlength(name); /* No ext, use the now one */ ext=extension; } if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN ) { /* To long path, return original or NULL */ size_t tmp_length; if (flag & MY_SAFE_PATH) DBUG_RETURN(NullS); tmp_length= strlength(startpos); DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %u",dev,ext, (uint) length)); (void) strmake(to, startpos, MY_MIN(tmp_length, FN_REFLEN-1)); } else { if (to == startpos) { bmove(buff,(uchar*) name,length); /* Save name for last copy */ name=buff; } pos=strmake(strmov(to,dev),name,length); (void) strmov(pos,ext); /* Don't convert extension */ } /* If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do realpath if the file is a symbolic link */ if (flag & MY_RETURN_REAL_PATH) (void) my_realpath(to, to, MYF(flag & MY_RESOLVE_SYMLINKS ? MY_RESOLVE_LINK: 0)); else if (flag & MY_RESOLVE_SYMLINKS) { strmov(buff,to); (void) my_readlink(to, buff, MYF(0)); } DBUG_RETURN(to); } /* fn_format */
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"); memset(&file, 0, 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; memset(&m_info->by_key, 0, 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); }
MYRG_INFO *myrg_parent_open(const char *parent_name, int (*callback)(void*, const char*), void *callback_param) { MYRG_INFO *m_info; int rc; int errpos; int save_errno; int insert_method; uint length; uint dir_length; uint child_count; size_t name_buff_length; 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= my_open(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, 2); } 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. */ dir_length= dirname_part(parent_name_buff, parent_name, &name_buff_length); 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; if (!has_path(child_name_buff)) { VOID(strmake(parent_name_buff + dir_length, child_name_buff, sizeof(parent_name_buff) - 1 - dir_length)); VOID(cleanup_dirname(child_name_buff, parent_name_buff)); } else fn_format(child_name_buff, child_name_buff, "", "", 0); 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(my_close(fd, MYF(0))); VOID(pthread_mutex_init(&m_info->mutex, MY_MUTEX_INIT_FAST)); m_info->open_list.data= (void*) m_info; pthread_mutex_lock(&THR_LOCK_open); myrg_open_list= list_add(myrg_open_list, &m_info->open_list); pthread_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(m_info); /* purecov: begin inspected */ err: save_errno= my_errno; switch (errpos) { case 3: my_free((char*) m_info, MYF(0)); /* Fall through */ case 2: end_io_cache(&file_cache); /* Fall through */ case 1: VOID(my_close(fd, MYF(0))); } my_errno= save_errno; DBUG_RETURN (NULL); /* purecov: end */ }
my_string fn_format(my_string to, const char *name, const char *dsk, const char *form, int flag) { reg1 uint length; char dev[FN_REFLEN], buff[BUFF_LEN], *pos, *startpos; const char *ext; DBUG_ENTER("fn_format"); DBUG_PRINT("enter",("name: %s dsk: %s form: %s flag: %d", name,dsk,form,flag)); /* Kopiera & skippa enheten */ name+=(length=dirname_part(dev,(startpos=(my_string) name))); if (length == 0 || flag & 1) { (void) strmake(dev,dsk, sizeof(dev) - 2); /* Use given directory */ convert_dirname(dev); /* Fix to this OS */ } if (flag & 8) pack_dirname(dev,dev); /* Put in ./.. and ~/.. */ if (flag & 4) (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */ if ((pos=(char*)strchr(name,FN_EXTCHAR)) != NullS) { if ((flag & 2) == 0) /* Skall vi byta extension ? */ { length=strlength(name); /* Old extension */ ext = ""; } else { length=(uint) (pos-(char*) name); /* Change extension */ ext= form; } } else { length=strlength(name); /* Har ingen ext- tag nya */ ext=form; } if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN ) { /* To long path, return original */ uint tmp_length; if (flag & 64) return 0; tmp_length=strlength(startpos); DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %d",dev,ext,length)); (void) strmake(to,startpos,min(tmp_length,FN_REFLEN-1)); } else { if (to == startpos) { bmove(buff,(char*) name,length); /* Save name for last copy */ name=buff; } pos=strmake(strmov(to,dev),name,length); #ifdef FN_UPPER_CASE caseup_str(to); #endif #ifdef FN_LOWER_CASE casedn_str(to); #endif (void) strmov(pos,ext); /* Don't convert extension */ } /* Purify gives a lot of UMR errors when using realpath */ #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) if (flag & 16) { struct stat stat_buff; if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode))) { if (realpath(to,buff)) strmake(to,buff,FN_REFLEN-1); } } #endif DBUG_RETURN (to); } /* fn_format */
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,i,errpos; uint files,dir_length,length,key_parts; ulonglong file_offset; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO info,*m_info; File fd; IO_CACHE file; MI_INFO *isam,*last_isam; DBUG_ENTER("myrg_open"); LINT_INIT(last_isam); LINT_INIT(m_info); isam=0; errpos=files=0; bzero((gptr) &info,sizeof(info)); bzero((char*) &file,sizeof(file)); if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), O_RDONLY | O_SHARE,MYF(0))) < 0 || init_io_cache(&file, fd, IO_SIZE, READ_CACHE, 0, 0, MYF(MY_WME | MY_NABP))) goto err; errpos=1; dir_length=dirname_part(name_buff,name); info.reclength=0; while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) { if ((end=buff+length)[-1] == '\n') end[-1]='\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,2); info.merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); } continue; /* Skip comments */ } if (!test_if_hard_path(buff)) { VOID(strmake(name_buff+dir_length,buff, sizeof(name_buff)-1-dir_length)); VOID(cleanup_dirname(buff,name_buff)); } if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) goto err; files++; last_isam=isam; if (info.reclength && info.reclength != isam->s->base.reclength) { my_errno=HA_ERR_WRONG_MRG_TABLE_DEF; goto err; } info.reclength=isam->s->base.reclength; } key_parts=(isam ? isam->s->base.key_parts : 0); if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+ files*sizeof(MYRG_TABLE)+ sizeof(long)*key_parts, MYF(MY_WME)))) goto err; *m_info=info; m_info->tables=files; if (files) { m_info->open_tables=(MYRG_TABLE *) (m_info+1); m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); bzero((char*) m_info->rec_per_key_part,sizeof(long)*key_parts); } else { m_info->open_tables=0; m_info->rec_per_key_part=0; } errpos=2; for (i=files ; i-- > 0 ; ) { uint j; m_info->open_tables[i].table=isam; 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; for (j=0; j < key_parts; j++) m_info->rec_per_key_part[j]+=isam->s->state.rec_per_key_part[j] / files; if (i) isam=(MI_INFO*) (isam->open_list.next->data); } /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); /* Fix fileinfo for easyer debugging (actually set by rrnd) */ file_offset=0; for (i=0 ; (uint) i < files ; i++) { m_info->open_tables[i].file_offset=(my_off_t) file_offset; file_offset+=m_info->open_tables[i].table->state->data_file_length; } if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) { my_errno=HA_ERR_RECORD_FILE_FULL; goto err; } m_info->keys=(files) ? m_info->open_tables->table->s->base.keys : 0; 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; VOID(my_close(fd,MYF(0))); end_io_cache(&file); m_info->open_list.data=(void*) m_info; pthread_mutex_lock(&THR_LOCK_open); myrg_open_list=list_add(myrg_open_list,&m_info->open_list); pthread_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(m_info); err: save_errno=my_errno; switch (errpos) { case 2: my_free((char*) m_info,MYF(0)); /* Fall through */ case 1: VOID(my_close(fd,MYF(0))); end_io_cache(&file); for (i=files ; i-- > 0 ; ) { isam=last_isam; if (i) last_isam=(MI_INFO*) (isam->open_list.next->data); mi_close(isam); } } my_errno=save_errno; DBUG_RETURN (NULL); }