Bug #72340 my_print_defaults fails to parse include directive if there is no new line
Submitted: 14 Apr 2014 12:02 Modified: 17 Apr 2014 16:53
Reporter: Olle Nilsson Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:5.6 OS:Linux
Assigned to: CPU Architecture:Any

[14 Apr 2014 12:02] Olle Nilsson
Description:
If an include directive is not followed by a newline in my.cnf, my_print_defaults fails to parse the file name of the file to include. The last letter of the file name is chopped off:

---
olle@ollen:[tmp]$ ls -l my*.cnf
-rw-r--r-- 1 olle olle 32 Apr 14 12:29 my.inc.cnf
-rw-r--r-- 1 olle olle 43 Apr 14 13:50 my.test.cnf

olle@ollen:[tmp]$ cat my.test.cnf 
[mysqld]
!include /home/olle/tmp/my.inc.cnfolle@ollen:[tmp]$ 
olle@ollen:[tmp]$ cat my.inc.cnf 
[mysqld]
datadir=/will/this/workolle@ollen:[tmp]$ 

olle@ollen:[tmp]$ strace -vfo /tmp/strace.out my_print_defaults --defaults-file=my.test.cnf mysqld
olle@ollen:[tmp]$ grep inc /tmp/strace.out 
19076 read(3, "[mysqld]\n!include /home/olle/tmp"..., 4096) = 43
19076 stat("/home/olle/tmp/my.inc.cn", 0x7fff64830010) = -1 ENOENT (No such file or directory)
---

This following code in my_default.cc might be the offender:
---
  /*
    Trim trailing whitespace from directory name
    The -1 below is for the newline added by fgets()
    Note that my_isspace() is true for \r and \n
  */
  for (end= ptr + strlen(ptr) - 1;
       my_isspace(&my_charset_latin1, *(end - 1));
       end--)
  {}
  end[0]= 0;                                    /* Cut off end space */
---

The comment in that code seems to be incorrect. man fgets on my system says:
---
fgets()  reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.  Reading stops after an EOF or a newline.  If a newline is read, it is stored into the buffer.  A terminating
       null byte ('\0') is stored after the last character in the buffer.
---

How to repeat:
olle@ollen:[tmp]$ echo "[mysqld]" > my.test.cnf && echo -n '!include /home/olle/tmp/my.inc.cnf' > my.test.cnf && echo -en "[mysqld]\ndatadir=included-parameter" > my.inc.cnf
olle@ollen:[tmp]$ my_print_defaults --defaults-file=my.test.cnf mysqld
olle@ollen:[tmp]$ echo >> my.test.cnf
olle@ollen:[tmp]$ my_print_defaults --defaults-file=my.test.cnf mysqld
--datadir=included-parameter

echo "[mysqld]" > my.test.cnf && echo -n '!include /home/olle/tmp/my.inc.cnf' > my.test.cnf && echo -en "[mysqld]\ndatadir=included-parameter" > my.inc.cnf
my_print_defaults --defaults-file=my.test.cnf mysqld
echo >> my.test.cnf
my_print_defaults --defaults-file=my.test.cnf mysqld

Suggested fix:
If new-line, remove last char returned by fgets, otherwise keep.
[15 Apr 2014 18:39] Sveta Smirnova
Thank you for the report.

I can not repeat described behavior:

$ cat my.parent.cnf 
[mysqld]
!include /home/sveta/SharedData/web_project/MySQL/bugs/bug72340/my.cnf
$ cat my.cnf 
[mysqld]
datadir=/will/this/work$ ~/build/mysql-5.6/bin/my_print_defaults --defaults-file=./my.parent.cnf mysqld
--datadir=/will/this/work

Plrease indicate which exact package of MySQL you use (file name you downloaded).
[16 Apr 2014 7:31] Olle Nilsson
Thanks for looking into this Sveta.

It appears you really do have a newline in your parent my.cnf. Otherwise your cat command would should the include file with the prompt "glued" to the end? 

Perhaps you edited using vi, it adds a newline silently by default. This bit me when I tried to reproduce the first time.

I am using:
mysql-5.6.16-linux-glibc2.5-x86_64, tar.gz download.

However, I just verified the bug in 5.1 and 5.5 aswell:

olle@ollen:[tmp]$ cat my.test.cnf 
!include /home/olle/tmp/my.inc.cnfolle@ollen:[tmp]$    ## No new line
olle@ollen:[tmp]$ 
olle@ollen:[tmp]$ # Testing 5.1, tar.gz download
olle@ollen:[tmp]$ /home/olle/src/5.1.73/bin/my_print_defaults --defaults-file=my.test.cnf mysqld
olle@ollen:[tmp]$ 
olle@ollen:[tmp]$ # Testing 5.5, tar.gz download
olle@ollen:[tmp]$ /home/olle/src/5.5.37/bin/my_print_defaults --defaults-file=my.test.cnf mysqld
olle@ollen:[tmp]$ 
olle@ollen:[tmp]$ # Adding a newline
olle@ollen:[tmp]$ echo >> my.test.cnf
olle@ollen:[tmp]$ 
olle@ollen:[tmp]$ # Testing 5.1, tar.gz download
olle@ollen:[tmp]$ /home/olle/src/5.1.73/bin/my_print_defaults --defaults-file=my.test.cnf mysqld
--datadir=included-parameter
olle@ollen:[tmp]$ # Success
olle@ollen:[tmp]$ 
olle@ollen:[tmp]$ # Testing 5.5, tar.gz download
olle@ollen:[tmp]$ /home/olle/src/5.5.37/bin/my_print_defaults --defaults-file=my.test.cnf mysqld
--datadir=included-parameter
olle@ollen:[tmp]$ # Success
[17 Apr 2014 16:53] Sveta Smirnova
Thank you for the feedback.

I misread your instructions and thought that new line symbol should be off the child file. If leading new line symbol exists in parent file issue is perfectly repeatable.
[17 Apr 2014 16:54] Sveta Smirnova
Parent file which cannot be read properly

Attachment: my.parent.cnf (application/octet-stream, text), 79 bytes.

[17 Apr 2014 16:54] Sveta Smirnova
include file

Attachment: my.cnf (application/octet-stream, text), 32 bytes.