diff options
Diffstat (limited to 'mysys/default_modify.c')
-rw-r--r-- | mysys/default_modify.c | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/mysys/default_modify.c b/mysys/default_modify.c index 00caa7beed6..ea384f9f27a 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -20,6 +20,8 @@ #include <my_dir.h> #define BUFF_SIZE 1024 +/* should be big enough to handle at least one line */ +#define RESERVE 1024 #ifdef __WIN__ #define NEWLINE "\r\n" @@ -66,8 +68,11 @@ int modify_defaults_file(const char *file_location, const char *option, FILE *cnf_file; MY_STAT file_stat; char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; - uint opt_len, optval_len, sect_len, nr_newlines= 0; + uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; + uint reserve_extended= 1, old_opt_len= 0; + uint new_opt_len; + int reserve_occupied= 0; DBUG_ENTER("modify_defaults_file"); if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) @@ -75,28 +80,33 @@ int modify_defaults_file(const char *file_location, const char *option, /* my_fstat doesn't use the flag parameter */ if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) - goto err; + goto malloc_err; opt_len= (uint) strlen(option); optval_len= (uint) strlen(option_value); + new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; + + /* calculate the size of the buffer we need */ + buffer_size= sizeof(char) * (file_stat.st_size + + /* option name len */ + opt_len + + /* reserve for '=' char */ + 1 + + /* option value len */ + optval_len + + /* reserve space for newline */ + NEWLINE_LEN + + /* The ending zero */ + 1 + + /* reserve some additional space */ + RESERVE); + /* Reserve space to read the contents of the file and some more for the option we want to add. */ - if (!(file_buffer= (char*) my_malloc(sizeof(char) * - (file_stat.st_size + - /* option name len */ - opt_len + - /* reserve space for newline */ - NEWLINE_LEN + - /* reserve for '=' char */ - 1 + - /* option value len */ - optval_len + - /* The ending zero */ - 1), MYF(MY_WME)))) - + if (!(file_buffer= (char*) my_malloc(buffer_size, MYF(MY_WME)))) goto malloc_err; sect_len= (uint) strlen(section_name); @@ -115,13 +125,37 @@ int modify_defaults_file(const char *file_location, const char *option, } /* correct the option */ - if (!opt_applied && in_section && !strncmp(src_ptr, option, opt_len) && + if (in_section && !strncmp(src_ptr, option, opt_len) && (*(src_ptr + opt_len) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || *(src_ptr + opt_len) == '\0')) { + /* + we should change all options. If opt_applied is set, we are running + into reserved memory area. Hence we should check for overruns. + */ + if (opt_applied) + { + src_ptr+= opt_len; /* If we correct an option, we know it's name */ + old_opt_len= opt_len; + + while (*src_ptr++) /* Find the end of the line */ + old_opt_len++; + + /* could be negative */ + reserve_occupied+= (int) new_opt_len - (int) old_opt_len; + if ((int) reserve_occupied > (int) (RESERVE*reserve_extended)) + { + if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size + + RESERVE*reserve_extended, + MYF(MY_WME|MY_FREE_ON_ERROR)))) + goto malloc_err; + reserve_extended++; + } + } + else + opt_applied= 1; dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - opt_applied= 1; } else { |