Bug #22807 mysql_upgrade fails when called with a basedir-path containing spaces
Submitted: 28 Sep 2006 22:55 Modified: 2 Feb 2007 2:59
Reporter: Armin Schöffmann (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:mysql-5.0.34-nightly-20061217 OS:Windows (win32)
Assigned to: Iggy Galarza CPU Architecture:Any
Tags: mysql_upgrade, pathname case sensitivity

[28 Sep 2006 22:55] Armin Schöffmann
Description:
mysql_upgrade still doesn't make it...

If mysql_upgrade is called on a system where the mysql-basedir points to a directory with its fullpath containing whitespaces, the call to the nested processes 'mysqlcheck.exe' and 'mysql.exe' fails.

1) The main reason is, that mysql_upgrade doesn't escape a path containing spaces with double-quotes, as it is required on windows-systems.

2) From within mysql_upgrade a call to 'mysql.exe' is made to execute the script 'mysql_fix_privilege_tables.sql'.  The full-path to this sql-script will also contain white-spaces in the above case. Due to the design of the used C-lib call "system(const char cmd_line)", windows can't handle a 2nd quoted path as part of the cmd-line args, as it removes the double-quotes from any other parameter than the module-path. ('system' calls 'cmd.exe /c' which has this behaviour).

How to repeat:
install mysql in a basedir containing white-spaces e.g.
"c:\programme\mysql 5.0" or "e:\program files\mysql"

C:\Programme\mysql 5.0\bin>mysql_upgrade --basedir="c:\programme\mysql 5.0"
Das System kann die angegebene Datei nicht finden.

E:\Program Files\MySQL\bin>mysql_upgrade --basedir=e:\program files\mysql
Can't find program 'e:\program\bin\mysqlcheck.exe'
Please restart with --basedir=mysql-install-directory

E:\Program Files\MySQL\bin>mysql_upgrade --basedir="e:\program files\mysql"
'e:\program' is not recognized as an internal or external command,
operable program or batch file.
Error executing 'e:\program files\mysql\bin\mysqlcheck.exe --check-upgrade --all
-databases --auto-repair --user=root'

Suggested fix:
The attached fix against mysql_upgrade.c works in 2 steps:

1) It constructs a correctly quoted full-path for mysqlcheck.exe, mysql.exe and the fullpath to the mysql_fix_privilege_tables.sql script (main). 

2) It introduces a new-helper function my_system(const char* psz_cmdline)
which replaces the system()-call by the win32 CreateProcess-function.
#ifdef __WIN__
#define system my_system
#endif

In contrary to system() CreateProcess() keeps the provided args untouched and therefor calls mysql.exe with a fully-qualified path to mysql_fix_privilege_tables.sql.

Probably, functions like 'unpack_filename' seem to be a better place to perform path-escaping for win32 builds, anyway, I don't have that deep insight on the mysql-source-code, to exclude side-effects on other functions.

It would be a good idea, to verify other nested mysql-tools in respect to the correct usage of quoted pathes in cmd-args. IMHO any tool that uses the "system" call and provides there a quoted fullpath in the cmd-line args will fail.

Todo: Check the correct path-handling of an additional defaults-file

Additionally, a standard-testcase, verifying the correct behaviour of a mysql-installation in a folder containing white-spaces would be highly recommended: The default location for applications on an english win-system contains already white spaces ("\program files..."
[28 Sep 2006 22:56] Armin Schöffmann
patched mysql_upgrade.c

Attachment: mysql_upgrade.c (text/plain), 15.15 KiB.

[29 Sep 2006 0:44] MySQL Verification Team
Thank you for the bug report.

miguel@hegel:~/dbs/mysql-5.0> bk changes | head
ChangeSet@1.2288, 2006-09-27 20:11:11+05:00, gluh@mysql.com +3 -0
  additional 'after merge' fix

ChangeSet@1.2287, 2006-09-27 19:21:29+05:00, gluh@mysql.com +8 -0
  after merge fix

ChangeSet@1.2286, 2006-09-27 18:06:46+05:00, gluh@mysql.com +7 -0
  Merge mysql.com:/home/gluh/MySQL/Merge/4.1
  into  mysql.com:/home/gluh/MySQL/Merge/5.0
  MERGE: 1.1616.2144.199
miguel@hegel:~/dbs/mysql-5.0>

D:\Program Files\MySQL\MySQL 5.0\bin>uname -a
WindowsNT light 2 5 x86

D:\Program Files\MySQL\MySQL 5.0\bin>mysql_upgrade --basedir="D:\Program Files\MySQL\MySQL 5.0"
'D:\Program' is not recognized as an internal or external command,
operable program or batch file.
Error executing 'D:\Program Files\MySQL\MySQL 5.0\bin\mysqlcheck.exe --check-upgrade --all-databases --auto-repair --user=root'

D:\Program Files\MySQL\MySQL 5.0\bin>mysql_upgrade --basedir="D:/Program Files/MySQL/MySQL 5.0/"
'D:\Program' is not recognized as an internal or external command,
operable program or batch file.
Error executing 'D:\Program Files\MySQL\MySQL 5.0\bin\mysqlcheck.exe'

D:\Program Files\MySQL\MySQL 5.0\bin>mysql_upgrade
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.func                                         OK
mysql.help_category                                OK
mysql.help_keyword                                 OK
mysql.help_relation                                OK
mysql.help_topic                                   OK
mysql.host                                         OK
mysql.proc                                         OK
mysql.procs_priv                                   OK
mysql.tables_priv                                  OK
mysql.time_zone                                    OK
mysql.time_zone_leap_second                        OK
mysql.time_zone_name                               OK
mysql.time_zone_transition                         OK
mysql.time_zone_transition_type                    OK
mysql.user                                         OK
Could not find file mysql_fix_privilege_tables.sql
Please use --basedir to specify the directory where MySQL is installed
[29 Sep 2006 22:36] Peter Brawley
Under WinXP, 5.0.24a mysql_upgrade fails with a correct mysql installation path that has NO spaces.
[14 Dec 2006 20:04] Iggy Galarza
Marked bug#24684 as a duplicate of this.
[14 Dec 2006 21:34] Iggy Galarza
Bug#18156 is a partial duplicate.
[17 Dec 2006 19:58] Armin Schöffmann
The pending patch treats win32 file- and dirnames case-sensitive.
(strcmp(...) in mysql_upgrade.c/comp_names and my_lib.c)

Neither mysqld nor win32 follow this convention on winnt (although ntfs is capable of).

In my opinion, mysql_upgrade should stick to the same convention and treat pathnames case-insensitive.

With my setup - mysql-tabledir in "c:\program files\mysql 5.0\data\MySQL" -
mysql_upgrade would fail if just called with the basedir.

see also:
http://support.microsoft.com/kb/100625/en-us
[28 Dec 2006 6:38] Iggy Galarza
Hi Armin,

This behavior was not introduced by the proposed patch.  Please open a separate bug describing the case sensitivity symptom. I had a look at the line of code you mentioned and I think you're right... mysql_upgrade will fail iff:

the file user.frm has been manually renamed with different case.
the file mysql.exe has been manually renamed with different case.
the file mysqlcheck.exe has been manually renamed with different case.

I verified this with some quick tests. I can make mysql_upgrade fail by renaming any of the three file mentioned above. I ran a variety of tests and could not cause mysql_upgrade to fail due to a case sensitive path.  First I created two directories "d:\test" and "d:\te st" which are valid basedirs. I can execute:

mysql_upgrade.exe --basedir="d:\test"
mysql_upgrade.exe --basedir="d:\te st"
mysql_upgrade.exe --basedir="d:\TEST"
mysql_upgrade.exe --basedir="d:\TE ST"
mysql_upgrade.exe --basedir="d:\TeSt"
mysql_upgrade.exe --basedir="d:\Te St"

successfully.
[18 Jan 2007 16:38] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/18353

ChangeSet@1.2363, 2007-01-18 11:38:05-05:00, iggy@recycle.(none) +3 -0
  Bug#22807 mysql_upgrade fails when called with a basedir-path containing spaces
  - Create space safe strings for system() calls in mysql_upgrade.exe
[19 Jan 2007 18:09] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/18462

ChangeSet@1.2364, 2007-01-19 13:09:48-05:00, iggy@recycle.(none) +1 -0
  Bug#22807 mysql_upgrade fails when called with a basedir-path containing spaces
  - Corrected compiler warnings and performance problems with new 
  dynstr_append_os_quoted function.
[31 Jan 2007 19:15] Chad MILLER
Available in 5.0.36, 5.1.15-beta.
[2 Feb 2007 2:59] Paul DuBois
Noted in 5.0.36, 5.1.15 changelogs.