size_t unpack_dirname(char * to, const char *from) { size_t length, h_length; char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; DBUG_ENTER("unpack_dirname"); length= normalize_dirname(buff, from); if (buff[0] == FN_HOMELIB) { suffix=buff+1; tilde_expansion=expand_tilde(&suffix); if (tilde_expansion) { length-= (size_t) (suffix-buff)-1; if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN) { if ((h_length > 0) && (tilde_expansion[h_length-1] == FN_LIBCHAR)) h_length--; if (buff+h_length < suffix) bmove(buff+h_length,suffix,length); else bmove_upp((uchar*) buff+h_length+length, (uchar*) suffix+length, length); bmove(buff,tilde_expansion,h_length); } } } #ifdef USE_SYMDIR if (my_use_symdir) symdirget(buff); #endif DBUG_RETURN(system_filename(to,buff)); /* Fix for open */ } /* unpack_dirname */
void bchange(register char *dst, uint old_length, register const char *src, uint new_length, uint tot_length) { uint rest=tot_length-old_length; if (old_length < new_length) bmove_upp(dst+rest+new_length,dst+tot_length,rest); else bmove(dst+new_length,dst+old_length,rest); memcpy(dst,src,new_length); }
void bchange(register uchar *dst, size_t old_length, register const uchar *src, size_t new_length, size_t tot_length) { size_t rest=tot_length-old_length; if (old_length < new_length) bmove_upp(dst+rest+new_length,dst+tot_length,rest); else bmove(dst+new_length,dst+old_length,rest); memcpy(dst,src,new_length); }
uint unpack_dirname(my_string to, const char *from) { uint length,h_length; char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; DBUG_ENTER("unpack_dirname"); (void) intern_filename(buff,from); /* Change to intern name */ length= (uint) strlen(buff); /* Fix that '/' is last */ if (length && #ifdef FN_DEVCHAR buff[length-1] != FN_DEVCHAR && #endif buff[length-1] != FN_LIBCHAR && buff[length-1] != '/') { buff[length]=FN_LIBCHAR; buff[length+1]= '\0'; } length=cleanup_dirname(buff,buff); if (buff[0] == FN_HOMELIB) { suffix=buff+1; tilde_expansion=expand_tilde(&suffix); if (tilde_expansion) { length-=(uint) (suffix-buff)-1; if (length+(h_length= (uint) strlen(tilde_expansion)) <= FN_REFLEN) { if (tilde_expansion[h_length-1] == FN_LIBCHAR) h_length--; if (buff+h_length < suffix) bmove(buff+h_length,suffix,length); else bmove_upp(buff+h_length+length,suffix+length,length); bmove(buff,tilde_expansion,h_length); } } } #ifdef USE_SYMDIR if (my_use_symdir) symdirget(buff); #endif DBUG_RETURN(system_filename(to,buff)); /* Fix for open */ } /* unpack_dirname */
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, int *warning) { ulong date[5]; ulonglong value; const char *end=str+length, *end_of_days; my_bool found_days,found_hours; uint state; l_time->neg=0; *warning= 0; for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) length--; if (str != end && *str == '-') { l_time->neg=1; str++; length--; } if (str == end) return 1; /* Check first if this is a full TIMESTAMP */ if (length >= 12) { /* Probably full timestamp */ int was_cut; enum enum_mysql_timestamp_type res= str_to_datetime(str, length, l_time, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut); if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR) { if (was_cut) *warning|= MYSQL_TIME_WARN_TRUNCATED; return res == MYSQL_TIMESTAMP_ERROR; } } /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); /* Skip all space after 'days' */ end_of_days= str; for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++) ; LINT_INIT(state); found_days=found_hours=0; if ((uint) (end-str) > 1 && str != end_of_days && my_isdigit(&my_charset_latin1, *str)) { /* Found days part */ date[0]= (ulong) value; state= 1; /* Assume next is hours */ found_days= 1; } else if ((end-str) > 1 && *str == time_separator && my_isdigit(&my_charset_latin1, str[1])) { date[0]= 0; /* Assume we found hours */ date[1]= (ulong) value; state=2; found_hours=1; str++; /* skip ':' */ } else { /* String given as one number; assume HHMMSS format */ date[0]= 0; date[1]= (ulong) (value/10000); date[2]= (ulong) (value/100 % 100); date[3]= (ulong) (value % 100); state=4; goto fractional; } /* Read hours, minutes and seconds */ for (;;) { for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); date[state++]= (ulong) value; if (state == 4 || (end-str) < 2 || *str != time_separator || !my_isdigit(&my_charset_latin1,str[1])) break; str++; /* Skip time_separator (':') */ } if (state != 4) { /* Not HH:MM:SS */ /* Fix the date to assume that seconds was given */ if (!found_hours && !found_days) { bmove_upp((uchar*) (date+4), (uchar*) (date+state), sizeof(long)*(state-1)); bzero((uchar*) date, sizeof(long)*(4-state)); } else bzero((uchar*) (date+state), sizeof(long)*(4-state)); } fractional: /* Get fractional second part */ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) { int field_length= 5; str++; value=(uint) (uchar) (*str - '0'); while (++str != end && my_isdigit(&my_charset_latin1, *str)) { if (field_length-- > 0) value= value*10 + (uint) (uchar) (*str - '0'); } if (field_length > 0) value*= (long) log_10_int[field_length]; else if (field_length < 0) *warning|= MYSQL_TIME_WARN_TRUNCATED; date[4]= (ulong) value; } else date[4]=0; /* Check for exponent part: E<gigit> | E<sign><digit> */ /* (may occur as result of %g formatting of time value) */ if ((end - str) > 1 && (*str == 'e' || *str == 'E') && (my_isdigit(&my_charset_latin1, str[1]) || ((str[1] == '-' || str[1] == '+') && (end - str) > 2 && my_isdigit(&my_charset_latin1, str[2])))) return 1; if (internal_format_positions[7] != 255) { /* Read a possible AM/PM */ while (str != end && my_isspace(&my_charset_latin1, *str)) str++; if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) { if (str[0] == 'p' || str[0] == 'P') { str+= 2; date[1]= date[1]%12 + 12; } else if (str[0] == 'a' || str[0] == 'A') str+=2; } } /* Integer overflow checks */ if (date[0] > UINT_MAX || date[1] > UINT_MAX || date[2] > UINT_MAX || date[3] > UINT_MAX || date[4] > UINT_MAX) return 1; l_time->year= 0; /* For protocol::store_time */ l_time->month= 0; l_time->day= date[0]; l_time->hour= date[1]; l_time->minute= date[2]; l_time->second= date[3]; l_time->second_part= date[4]; l_time->time_type= MYSQL_TIMESTAMP_TIME; /* Check if the value is valid and fits into MYSQL_TIME range */ if (check_time_range(l_time, warning)) return 1; /* Check if there is garbage at end of the MYSQL_TIME specification */ if (str != end) { do { if (!my_isspace(&my_charset_latin1,*str)) { *warning|= MYSQL_TIME_WARN_TRUNCATED; break; } } while (++str != end); } return 0; }
MY_DIR *my_dir(const char *path, myf MyFlags) { DIR *dirp; struct dirent *dp; struct fileinfo *fnames; char *buffer, *obuffer, *tempptr; uint fcnt,i,size,firstfcnt, maxfcnt,length; char tmp_path[FN_REFLEN+1],*tmp_file; my_ptrdiff_t diff; bool eof; #ifdef THREAD char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; #endif DBUG_ENTER("my_dir"); DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); #if defined(THREAD) && !defined(HAVE_READDIR_R) pthread_mutex_lock(&THR_LOCK_open); #endif dirp = opendir(directory_file_name(tmp_path,(my_string) path)); size = STARTSIZE; if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags))) goto error; fcnt = 0; tmp_file=strend(tmp_path); firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / (sizeof(struct fileinfo) + FN_LEN); fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); tempptr = (char *) (fnames + maxfcnt); #ifdef THREAD dp= (struct dirent*) dirent_tmp; #else dp=0; #endif eof=0; for (;;) { while (fcnt < maxfcnt && !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp))) { bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */ fnames[fcnt].name = tempptr; tempptr = strmov(tempptr,dp->d_name) + 1; if (MyFlags & MY_WANT_STAT) { VOID(strmov(tmp_file,dp->d_name)); VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags)); } ++fcnt; } if (eof) break; size += STARTSIZE; obuffer = buffer; if (!(buffer = (char *) my_realloc((gptr) buffer, size, MyFlags | MY_FREE_ON_ERROR))) goto error; /* No memory */ length= (uint) (sizeof(struct fileinfo ) * firstfcnt); diff= PTR_BYTE_DIFF(buffer , obuffer) + (int) length; fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); tempptr= ADD_TO_PTR(tempptr,diff,char*); for (i = 0; i < maxfcnt; i++) fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); /* move filenames upp a bit */ maxfcnt += firstfcnt; bmove_upp(tempptr,tempptr-length, (uint) (tempptr- (char*) (fnames+maxfcnt))); } (void) closedir(dirp); { MY_DIR * s = (MY_DIR *) buffer; s->number_off_files = (uint) fcnt; s->dir_entry = fnames; } if (!(MyFlags & MY_DONT_SORT)) qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo), (qsort_cmp) comp_names); #if defined(THREAD) && !defined(HAVE_READDIR_R) pthread_mutex_unlock(&THR_LOCK_open); #endif DBUG_RETURN((MY_DIR *) buffer); error: #if defined(THREAD) && !defined(HAVE_READDIR_R) pthread_mutex_unlock(&THR_LOCK_open); #endif my_errno=errno; if (dirp) (void) closedir(dirp); if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno); DBUG_RETURN((MY_DIR *) NULL); } /* my_dir */
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status) { ulong date[5]; ulonglong value; const char *end=str+length, *end_of_days; my_bool found_days,found_hours, neg= 0; uint UNINIT_VAR(state); my_time_status_init(status); for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) length--; if (str != end && *str == '-') { neg=1; str++; length--; } if (str == end) { status->warnings|= MYSQL_TIME_WARN_TRUNCATED; goto err; } /* Check first if this is a full TIMESTAMP */ if (length >= 12) { /* Probably full timestamp */ (void) str_to_datetime(str, length, l_time, (fuzzydate & ~TIME_TIME_ONLY) | TIME_DATETIME_ONLY, status); if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR) return l_time->time_type == MYSQL_TIMESTAMP_ERROR; my_time_status_init(status); } l_time->neg= neg; /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); /* Skip all space after 'days' */ end_of_days= str; for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++) ; found_days=found_hours=0; if ((uint) (end-str) > 1 && str != end_of_days && my_isdigit(&my_charset_latin1, *str)) { /* Found days part */ date[0]= (ulong) value; state= 1; /* Assume next is hours */ found_days= 1; } else if ((end-str) > 1 && *str == time_separator && my_isdigit(&my_charset_latin1, str[1])) { date[0]= 0; /* Assume we found hours */ date[1]= (ulong) value; state=2; found_hours=1; str++; /* skip ':' */ } else { /* String given as one number; assume HHMMSS format */ date[0]= 0; date[1]= (ulong) (value/10000); date[2]= (ulong) (value/100 % 100); date[3]= (ulong) (value % 100); state=4; goto fractional; } /* Read hours, minutes and seconds */ for (;;) { for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); date[state++]= (ulong) value; if (state == 4 || (end-str) < 2 || *str != time_separator || !my_isdigit(&my_charset_latin1,str[1])) break; str++; /* Skip time_separator (':') */ } if (state != 4) { /* Not HH:MM:SS */ /* Fix the date to assume that seconds was given */ if (!found_hours && !found_days) { bmove_upp((uchar*) (date+4), (uchar*) (date+state), sizeof(long)*(state-1)); bzero((uchar*) date, sizeof(long)*(4-state)); } else bzero((uchar*) (date+state), sizeof(long)*(4-state)); } fractional: /* Get fractional second part */ if (!status->warnings && str < end && *str == '.') { uint number_of_fields= 0; str++; get_microseconds(&date[4], status, &number_of_fields, &str, end); } else date[4]= 0; /* Check for exponent part: E<gigit> | E<sign><digit> */ /* (may occur as result of %g formatting of time value) */ if ((end - str) > 1 && (*str == 'e' || *str == 'E') && (my_isdigit(&my_charset_latin1, str[1]) || ((str[1] == '-' || str[1] == '+') && (end - str) > 2 && my_isdigit(&my_charset_latin1, str[2])))) { status->warnings|= MYSQL_TIME_WARN_TRUNCATED; goto err; } if (internal_format_positions[7] != 255) { /* Read a possible AM/PM */ while (str != end && my_isspace(&my_charset_latin1, *str)) str++; if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) { if (str[0] == 'p' || str[0] == 'P') { str+= 2; date[1]= date[1]%12 + 12; } else if (str[0] == 'a' || str[0] == 'A') str+=2; } } /* Integer overflow checks */ if (date[0] > UINT_MAX || date[1] > UINT_MAX || date[2] > UINT_MAX || date[3] > UINT_MAX || date[4] > UINT_MAX) { status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; goto err; } l_time->year= 0; /* For protocol::store_time */ l_time->month= 0; l_time->day= 0; l_time->hour= date[1] + date[0] * 24; /* Mix days and hours */ l_time->minute= date[2]; l_time->second= date[3]; l_time->second_part= date[4]; l_time->time_type= MYSQL_TIMESTAMP_TIME; /* Check if the value is valid and fits into MYSQL_TIME range */ if (check_time_range(l_time, 6, &status->warnings)) return TRUE; /* Check if there is garbage at end of the MYSQL_TIME specification */ if (str != end) { do { if (!my_isspace(&my_charset_latin1,*str)) { status->warnings|= MYSQL_TIME_WARN_TRUNCATED; break; } } while (++str != end); } return FALSE; err: bzero((char*) l_time, sizeof(*l_time)); l_time->time_type= MYSQL_TIMESTAMP_ERROR; return TRUE; }
static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size) { double check_trunc_val= (val > 0) ? floor(val) : -floor(-val); char *buf= (char *)r_param->buffer; switch (r_param->buffer_type) { case MYSQL_TYPE_TINY: *buf= (r_param->is_unsigned) ? (uint8)val : (int8)val; *r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) : (double)((int8)*buf)); r_param->buffer_length= 1; break; case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: { if (r_param->is_unsigned) { ushort sval= (ushort)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } else { short sval= (short)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } r_param->buffer_length= 2; } break; case MYSQL_TYPE_LONG: { if (r_param->is_unsigned) { uint32 lval= (uint32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } else { int32 lval= (int32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } r_param->buffer_length= 4; } break; case MYSQL_TYPE_LONGLONG: { if (r_param->is_unsigned) { ulonglong llval= (ulonglong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } else { longlong llval= (longlong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } r_param->buffer_length= 8; } break; case MYSQL_TYPE_FLOAT: { float fval= (float)val; memcpy(buf, &fval, sizeof(float)); *r_param->error= (*(float*)buf != fval); r_param->buffer_length= 4; } break; case MYSQL_TYPE_DOUBLE: { memcpy(buf, &val, sizeof(double)); r_param->buffer_length= 8; } break; default: { #define MAX_DOUBLE_STRING_REP_LENGTH 300 char buff[MAX_DOUBLE_STRING_REP_LENGTH]; char *end; size_t length; length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length); if (field->decimals >= NOT_FIXED_DEC) { sprintf(buff, "%-*.*g", (int) length-1, DBL_DIG, val); length= strlen(buff); } else { sprintf(buff, "%.*f", field->decimals, val); length= strlen(buff); } /* remove possible trailing blanks */ if ((end= strcend(buff, ' '))) *end= 0; /* check if ZEROFILL flag is active */ if (field->flags & ZEROFILL_FLAG) { /* enough space available ? */ if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1) break; bmove_upp(buff + field->length, buff + length, length); bfill((char*) buff, field->length - length, '0'); } convert_from_string(r_param, buff, strlen(buff)); } break; } }