Commit 5643df2d authored by unknown's avatar unknown
Browse files

Fixes in function modify_defaults_file():

- Removed unneccessary variables.
- Made a function of that part of code, which actually changes 
  the line under modifications.
- Fixed memory overrun problem with my_malloc. Too little space
  was reserved.
- Fixed problem in case, when new option was added at the end
  of the section. Before, it was added as the last line of the
  section, even if it left empty lines between.
- Fixed so that the configuration file is not saved unneccessarily,
  if no modifications are done. (file timestamp remains)
- This should fix (at least partially) problems described in
  Bug#10806

parent 9227cf42
Loading
Loading
Loading
Loading
+69 −46
Original line number Diff line number Diff line
@@ -37,22 +37,20 @@
#define NEWLINE_LEN 1
#endif

static char *add_option(char *dst, const char *option_value,
			const char *option, int remove_option);

int modify_defaults_file(const char *file_location, const char *option,
                         const char *option_value,
                         const char *section_name, int remove_option)
{
  FILE *cnf_file;
  MY_STAT file_stat;
  char linebuff[BUFF_SIZE], tmp[BUFF_SIZE], *tmp_ptr, *src_ptr, *dst_ptr,
       *file_buffer;
  uint optlen, optval_len, sect_len;
  my_bool in_section= FALSE;
  char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
  uint optlen, optval_len, sect_len, nr_newlines= 0;
  my_bool in_section= FALSE, opt_applied= 0;
  DBUG_ENTER("modify_defaults_file");

  optlen= strlen(option);
  optval_len= strlen(option_value);
  sect_len= strlen(section_name);

  if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
    DBUG_RETURN(2);

@@ -60,6 +58,9 @@ int modify_defaults_file(const char *file_location, const char *option,
  if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
    goto err;

  optlen= strlen(option);
  optval_len= strlen(option_value);

  /*
    Reserve space to read the contents of the file and some more
    for the option we want to add.
@@ -73,35 +74,44 @@ int modify_defaults_file(const char *file_location, const char *option,
					/* reserve for '=' char */
					1 +           
					/* option value len */
					optval_len), MYF(MY_WME))))
					optval_len +
					/* The ending zero plus some safety */
					FN_REFLEN), MYF(MY_WME))))
    goto malloc_err;

  for (dst_ptr= file_buffer, tmp_ptr= 0;
       fgets(linebuff, BUFF_SIZE, cnf_file); )
  sect_len= strlen(section_name);

  for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); )
  {
    /* Skip over whitespaces */
    for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr);
	 src_ptr++)
    {}

    if (in_section && !strncmp(src_ptr, option, optlen) &&
    if (!*src_ptr) /* Empty line */
    {
      nr_newlines++;
      continue;
    }

    if (!opt_applied && in_section && !strncmp(src_ptr, option, optlen) &&
	(*(src_ptr + optlen) == '=' ||
	 my_isspace(&my_charset_latin1, *(src_ptr + optlen)) ||
	 *(src_ptr + optlen) == '\0'))
    {
      /* The option under modifying was found in this section. Apply new. */
      if (!remove_option)
	dst_ptr= strmov(dst_ptr, tmp);
      tmp_ptr= 0; /* To mark that we have already applied this */
      dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
      opt_applied= 1;
    }
    else
    {
      /* If going to new group and we have option to apply, do it now */
      if (tmp_ptr && *src_ptr == '[')
      if (in_section && !opt_applied && *src_ptr == '[')
      {
	dst_ptr= strmov(dst_ptr, tmp);
	tmp_ptr= 0;
	dst_ptr= add_option(dst_ptr, option_value, option, remove_option);

      }
      for (; nr_newlines; nr_newlines--)
	dst_ptr= strmov(dst_ptr, NEWLINE);	
      dst_ptr= strmov(dst_ptr, linebuff);
    }
    /* Look for a section */
@@ -117,43 +127,38 @@ int modify_defaults_file(const char *file_location, const char *option,

	if (*src_ptr != ']')
	  continue; /* Missing closing parenthesis. Assume this was no group */
	
        in_section= TRUE;
        /* add option */
        if (!remove_option)
        {
          tmp_ptr= strmov(tmp, option);
          if (*option_value)
          {
	    *tmp_ptr++= '=';
            tmp_ptr= strmov(tmp_ptr, option_value);
          }
          /* add a newline */
	  strmov(tmp_ptr, NEWLINE);
        }
      }
      else
        in_section= FALSE; /* mark that this section is of no interest to us */
    }
  }
  /* File ended. New option still remains to apply at the end */
  if (tmp_ptr)
  /* File ended. */
  if (!opt_applied && !remove_option && in_section)
  {
    /* New option still remains to apply at the end */
    if (*(dst_ptr - 1) != '\n')
      *dst_ptr++= '\n';
    dst_ptr= strmov(dst_ptr, tmp);    
      dst_ptr= strmov(dst_ptr, NEWLINE);
    dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
    opt_applied= 1;
  }
  for (; nr_newlines; nr_newlines--)
    dst_ptr= strmov(dst_ptr, NEWLINE);

  if (opt_applied)
  {
    /* Don't write the file if there are no changes to be made */
    if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
		  MYF(MY_WME)) ||
	my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
	my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
		MYF(MY_NABP)) ||
      my_fclose(cnf_file, MYF(MY_WME)))
		  MYF(MY_NABP)))
      goto err;
  }
  if (my_fclose(cnf_file, MYF(MY_WME)))
    goto err;

  my_free(file_buffer, MYF(0));

  DBUG_RETURN(0);

err:
@@ -162,3 +167,21 @@ int modify_defaults_file(const char *file_location, const char *option,
  my_fclose(cnf_file, MYF(0));
  DBUG_RETURN(1); /* out of resources */
}


static char *add_option(char *dst, const char *option_value,
			const char *option, int remove_option)
{
  if (!remove_option)
  {
    dst= strmov(dst, option);
    if (*option_value)
    {
      *dst++= '=';
      dst= strmov(dst, option_value);
    }
    /* add a newline */
    dst= strmov(dst, NEWLINE);
  }
  return dst;
}