From f5b4c8f1e5c0d51480b6d5dfc2f8b8fc94be96d0 Mon Sep 17 00:00:00 2001
From: Nirbhay Choubey <nirbhay.choubey@oracle.com>
Date: Thu, 21 Mar 2013 22:51:40 +0530
Subject: Bug#16500013 : ADD VERSION CHECK TO MYSQL_UPGRADE

(Based on Sinisa's patch)

Added a version checking facility to mysql_upgrade.
The versions used for checking is the version of the
server that mysql_upgrade is going to upgrade and the
server version that mysql_upgrade was build/distributed
with.
Also added an option '--version-check' to enable/disable
the version checking.
---
 client/mysql_upgrade.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 2 deletions(-)

(limited to 'client')

diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 8bbb8864afd..4a84679ae10 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+   Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@ static char mysql_path[FN_REFLEN];
 static char mysqlcheck_path[FN_REFLEN];
 
 static my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag,
-               opt_systables_only;
+               opt_systables_only, opt_version_check;
 static uint my_end_arg= 0;
 static char *opt_user= (char*)"root";
 
@@ -128,6 +128,12 @@ static struct my_option my_long_options[]=
    "Base name of shared memory.", 0,
    0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 #endif
+  {"version-check", 'k', "Run this program only if its \'server version\' "
+   "matches with the version of the server its connecting to, (enabled by "
+   "default); use --skip-version-check to avoid this check. Note: the \'server "
+   "version\' of the program is the version of the MySQL server with which it "
+   "was build/distributed.", &opt_version_check, &opt_version_check, 0,
+   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
   {"socket", 'S', "The socket file to use for connection.",
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 #include <sslopt-longopts.h>
@@ -283,6 +289,7 @@ get_one_option(int optid, const struct my_option *opt,
             my_progname, optid == 'b' ? "basedir" : "datadir");
     /* FALLTHROUGH */
 
+  case 'k':                                     /* --version-check */
   case 'v': /* --verbose   */
   case 'f': /* --force     */
   case 's':                                     /* --upgrade-system-tables */
@@ -824,6 +831,55 @@ static const char *load_default_groups[]=
 };
 
 
+/* Convert the specified version string into the numeric format. */
+static ulong STDCALL calc_server_version(char *some_version)
+{
+  uint major, minor, version;
+  char *point= some_version, *end_point;
+  major=   (uint) strtoul(point, &end_point, 10);   point=end_point+1;
+  minor=   (uint) strtoul(point, &end_point, 10);   point=end_point+1;
+  version= (uint) strtoul(point, &end_point, 10);
+  return (ulong) major * 10000L + (ulong)(minor * 100 + version);
+}
+
+/**
+  Check if the server version matches with the server version mysql_upgrade
+  was compiled with.
+
+  @return 0 match successful
+          1 failed
+*/
+static int check_version_match(void)
+{
+  DYNAMIC_STRING ds_version;
+  char version_str[NAME_CHAR_LEN + 1];
+
+  if (init_dynamic_string(&ds_version, NULL, NAME_CHAR_LEN, NAME_CHAR_LEN))
+    die("Out of memory");
+
+  if (run_query("show variables like 'version'",
+                &ds_version, FALSE) ||
+      extract_variable_from_show(&ds_version, version_str))
+  {
+    dynstr_free(&ds_version);
+    return 1;                                   /* Query failed */
+  }
+
+  dynstr_free(&ds_version);
+
+  if (calc_server_version((char *) version_str) != MYSQL_VERSION_ID)
+  {
+    fprintf(stderr, "Error: Server version (%s) does not match with the "
+            "version of\nthe server (%s) with which this program was build/"
+            "distributed. You can\nuse --skip-version-check to skip this "
+            "check.\n", version_str, MYSQL_SERVER_VERSION);
+    return 1;
+  }
+  else
+    return 0;
+}
+
+
 int main(int argc, char **argv)
 {
   char self_name[FN_REFLEN];
@@ -888,6 +944,9 @@ int main(int argc, char **argv)
     die(NULL);
   }
 
+  if (opt_version_check && check_version_match())
+    die("Upgrade failed");
+
   /*
     Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
   */
-- 
cgit v1.2.1