diff options
author | unknown <petr@mysql.com> | 2005-06-23 18:13:58 +0400 |
---|---|---|
committer | unknown <petr@mysql.com> | 2005-06-23 18:13:58 +0400 |
commit | 6311217a23cd8424ad10a23ee752141257275252 (patch) | |
tree | 88e26b77f00f43df3a5633d689880e7ea37dfc6b /mysys/default_modify.c | |
parent | cceab6e62c3496b7ae58e515e3ffc0f76be050de (diff) | |
download | mariadb-git-6311217a23cd8424ad10a23ee752141257275252.tar.gz |
Fix modify_defaults_file as agreed with monty (correct all occurences of an option in the section)
mysys/default_modify.c:
Correct all occurences of an option in the section. To avoid memory problems preallocate reserve of 1K, and
realloc it later if needed (almost never).
Diffstat (limited to 'mysys/default_modify.c')
-rw-r--r-- | mysys/default_modify.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/mysys/default_modify.c b/mysys/default_modify.c index 00caa7beed6..d40529817cd 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,10 @@ 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; + int reserve_occupied= 0, reserve_extended= 1, old_opt_len; + int new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; DBUG_ENTER("modify_defaults_file"); if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) @@ -80,23 +84,26 @@ int modify_defaults_file(const char *file_location, const char *option, opt_len= (uint) strlen(option); optval_len= (uint) strlen(option_value); + /* 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 +122,31 @@ 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) + { + old_opt_len= strlen(linebuff); + /* could be negative */ + reserve_occupied+= new_opt_len - old_opt_len; + if (reserve_occupied > RESERVE*reserve_extended) + { + file_buffer= (char*) my_realloc(file_buffer, buffer_size + + RESERVE*reserve_extended, + MYF(MY_WME)); + reserve_extended++; + } + } + else + opt_applied= 1; dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - opt_applied= 1; } else { |