#At file:///D:/source/bzr/mysql-6.0-bug-35230/
2648 Chuck Bell 2008-07-09
BUG#35230 Backup: no backupdir
This patch adds the dynamic variable --backupdir which specifies the path
where the image files are placed (backup) or accessed (restore) if a path
is not specified in the command.
modified:
mysql-test/r/backup_progress.result
mysql-test/t/backup_progress.test
sql/backup/backup_kernel.h
sql/backup/kernel.cc
sql/backup/stream.cc
sql/backup/stream.h
sql/mysqld.cc
sql/set_var.cc
sql/set_var.h
sql/share/errmsg.txt
sql/sql_parse.cc
per-file messages:
mysql-test/r/backup_progress.result
New result file.
mysql-test/t/backup_progress.test
Added a mask for backup location because this path will vary from
machine to machine.
sql/backup/backup_kernel.h
Changed methods to include original location from lex structure instead of
traversing the THD object.
sql/backup/kernel.cc
Added code to process the backupdir IFF there is no path specified
in the command.
sql/backup/stream.cc
Moved path processing to Stream::Stream. Constructors now take backupdir plus
original filename specified on command.
sql/backup/stream.h
Constructors now take backupdir plus original filename specified on command.
sql/mysqld.cc
Added code to support backupdir.
sql/set_var.cc
Added all of the methods needed to check, update, and set a default
for the backupdir variable.
sql/set_var.h
Added extern for backupdir variable named sys_var_backupdir.
sql/share/errmsg.txt
Added new error message for invalid backupdir paths.
sql/sql_parse.cc
Added processing of system variable for backupdir to remove dependency in
backup code.
=== modified file 'mysql-test/r/backup_progress.result'
--- a/mysql-test/r/backup_progress.result 2008-07-01 20:32:27 +0000
+++ b/mysql-test/r/backup_progress.result 2008-07-09 17:31:53 +0000
@@ -78,7 +78,7 @@ start_time #
stop_time #
host_or_server_name localhost
username root
-backup_file backup_progress_orig.bak
+backup_file #
user_comment
command BACKUP DATABASE backup_progress to 'backup_progress_orig.bak'
engines MyISAM, Default, Snapshot
@@ -135,7 +135,7 @@ start_time #
stop_time #
host_or_server_name localhost
username root
-backup_file backup_progress_orig.bak
+backup_file #
user_comment
command RESTORE FROM 'backup_progress_orig.bak'
engines MyISAM, Default, Snapshot
=== modified file 'mysql-test/t/backup_progress.test'
--- a/mysql-test/t/backup_progress.test 2008-06-25 13:39:04 +0000
+++ b/mysql-test/t/backup_progress.test 2008-07-09 17:31:53 +0000
@@ -107,7 +107,7 @@ connection con2;
reap;
#Show results
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
--query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res
AS t1 ON ob.backup_id = t1.id;
--replace_column 1 # 3 # 4 #
SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1
ON obp.backup_id = t1.id;
@@ -156,7 +156,7 @@ reap;
DELETE FROM backup_progress.t1_res;
SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE "RESTORE
FROM%";
INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
--query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res
AS t1 ON ob.backup_id = t1.id;
--replace_column 1 # 3 # 4 #
SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1
ON obp.backup_id = t1.id;
=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h 2008-06-26 12:10:46 +0000
+++ b/sql/backup/backup_kernel.h 2008-07-09 17:31:53 +0000
@@ -30,7 +30,7 @@ void backup_shutdown();
Called from the big switch in mysql_execute_command() to execute
backup related statement
*/
-int execute_backup_command(THD*, LEX*);
+int execute_backup_command(THD*, LEX*, String*);
// forward declarations
@@ -66,8 +66,12 @@ class Backup_restore_ctx: public backup:
bool is_valid() const;
ulonglong op_id() const;
- Backup_info* prepare_for_backup(LEX_STRING location, const char*, bool);
- Restore_info* prepare_for_restore(LEX_STRING location, const char*);
+ Backup_info* prepare_for_backup(String *location,
+ LEX_STRING orig_loc,
+ const char*, bool);
+ Restore_info* prepare_for_restore(String *location,
+ LEX_STRING orig_loc,
+ const char*);
int do_backup();
int do_restore();
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-07-01 13:34:36 +0000
+++ b/sql/backup/kernel.cc 2008-07-09 17:31:53 +0000
@@ -19,7 +19,8 @@
{
Backup_restore_ctx context(thd); // create context instance
- Backup_info *info= context.prepare_for_backup(location); // prepare for backup
+ Backup_info *info= context.prepare_for_backup(location,
+ orig_loc); // prepare for backup
// select objects to backup
info->add_all_dbs();
@@ -41,7 +42,8 @@
{
Backup_restore_ctx context(thd); // create context instance
- Restore_info *info= context.prepare_for_restore(location); // prepare for restore
+ Restore_info *info= context.prepare_for_restore(location,
+ orig_loc); // prepare for restore
context.do_restore(); // perform restore
@@ -111,7 +113,9 @@ static int send_reply(Backup_restore_ctx
/**
Call backup kernel API to execute backup related SQL statement.
- @param lex results of parsing the statement.
+ @param[IN] thd current thread object reference.
+ @param[IN] lex results of parsing the statement.
+ @param[IN] backupdir value of the backupdir variable from server.
@note This function sends response to the client (ok, result set or error).
@@ -119,7 +123,7 @@ static int send_reply(Backup_restore_ctx
*/
int
-execute_backup_command(THD *thd, LEX *lex)
+execute_backup_command(THD *thd, LEX *lex, String *backupdir)
{
int res= 0;
@@ -127,6 +131,7 @@ execute_backup_command(THD *thd, LEX *le
DBUG_ASSERT(thd && lex);
DEBUG_SYNC(thd, "before_backup_command");
+
using namespace backup;
Backup_restore_ctx context(thd); // reports errors
@@ -134,13 +139,24 @@ execute_backup_command(THD *thd, LEX *le
if (!context.is_valid())
DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_CREATE));
+ /*
+ Check backupdir for validity (needed since we cannot trust
+ that the path has become invalid since set).
+ */
+ if (backupdir->length() && my_access(backupdir->c_ptr(), (F_OK|W_OK)))
+ {
+ context.fatal_error(ER_BACKUP_BACKUPDIR, backupdir->c_ptr());
+ DBUG_RETURN(send_error(context, ER_BACKUP_BACKUPDIR, backupdir->c_ptr()));
+ }
+
switch (lex->sql_command) {
case SQLCOM_BACKUP:
{
// prepare for backup operation
- Backup_info *info= context.prepare_for_backup(lex->backup_dir, thd->query,
+ Backup_info *info= context.prepare_for_backup(backupdir, lex->backup_dir,
+ thd->query,
lex->backup_compression);
// reports errors
@@ -185,7 +201,8 @@ execute_backup_command(THD *thd, LEX *le
case SQLCOM_RESTORE:
{
- Restore_info *info= context.prepare_for_restore(lex->backup_dir, thd->query);
+ Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir,
+ thd->query);
if (!info || !info->is_valid())
DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -396,6 +413,11 @@ int Backup_restore_ctx::prepare(LEX_STRI
// check if location is valid (we assume it is a file path)
+ /*
+ For this error to work correctly, we need to check original
+ file specified by the user rather than the path formed
+ using the backupdir.
+ */
bool bad_filename= (location.length == 0);
/*
@@ -405,7 +427,7 @@ int Backup_restore_ctx::prepare(LEX_STRI
#if defined(__WIN__) || defined(__EMX__)
bad_filename = bad_filename || check_if_legal_filename(location.str);
-
+
#endif
if (bad_filename)
@@ -443,7 +465,8 @@ int Backup_restore_ctx::prepare(LEX_STRI
/**
Prepare for backup operation.
- @param[in] location path to the file where backup image should be stored
+ @param[in] backupdir path to the file where backup image should be stored
+ @param[in] orig_loc path as specified on command line for backup image
@param[in] query BACKUP query starting the operation
@param[in] with_compression backup image compression switch
@@ -458,7 +481,9 @@ int Backup_restore_ctx::prepare(LEX_STRI
is performed using @c do_backup() method.
*/
Backup_info*
-Backup_restore_ctx::prepare_for_backup(LEX_STRING location, const char *query,
+Backup_restore_ctx::prepare_for_backup(String *backupdir,
+ LEX_STRING orig_loc,
+ const char *query,
bool with_compression)
{
using namespace backup;
@@ -466,7 +491,7 @@ Backup_restore_ctx::prepare_for_backup(L
if (m_error)
return NULL;
- if (Logger::init(BACKUP, location, query))
+ if (Logger::init(BACKUP, orig_loc, query))
{
fatal_error(ER_BACKUP_LOGGER_INIT);
return NULL;
@@ -479,16 +504,16 @@ Backup_restore_ctx::prepare_for_backup(L
Do preparations common to backup and restore operations. After call
to prepare() all meta-data changes are blocked.
*/
- if (prepare(location))
+ if (prepare(orig_loc))
return NULL;
- backup::String path(location);
-
/*
Open output stream.
*/
-
- Output_stream *s= new Output_stream(*this, path, with_compression);
+ Output_stream *s= new Output_stream(*this,
+ backupdir,
+ orig_loc,
+ with_compression);
m_stream= s;
if (!s)
@@ -499,7 +524,11 @@ Backup_restore_ctx::prepare_for_backup(L
if (!s->open())
{
- fatal_error(ER_BACKUP_WRITE_LOC, path.ptr());
+ /*
+ For this error, use the actual value returned instead of the
+ path complimented with backupdir.
+ */
+ fatal_error(ER_BACKUP_WRITE_LOC, orig_loc.str);
return NULL;
}
@@ -528,7 +557,8 @@ Backup_restore_ctx::prepare_for_backup(L
/**
Prepare for restore operation.
- @param[in] location path to the file where backup image is stored
+ @param[in] backupdir path to the file where backup image is stored
+ @param[in] orig_loc path as specified on command line for backup image
@param[in] query RESTORE query starting the operation
@returns Pointer to a @c Restore_info instance containing catalogue of the
@@ -537,14 +567,16 @@ Backup_restore_ctx::prepare_for_backup(L
@note This function reports errors.
*/
Restore_info*
-Backup_restore_ctx::prepare_for_restore(LEX_STRING location, const char *query)
+Backup_restore_ctx::prepare_for_restore(String *backupdir,
+ LEX_STRING orig_loc,
+ const char *query)
{
using namespace backup;
if (m_error)
return NULL;
- if (Logger::init(RESTORE, location, query))
+ if (Logger::init(RESTORE, orig_loc, query))
{
fatal_error(ER_BACKUP_LOGGER_INIT);
return NULL;
@@ -557,15 +589,14 @@ Backup_restore_ctx::prepare_for_restore(
Do preparations common to backup and restore operations. After this call
changes of meta-data are blocked.
*/
- if (prepare(location))
+ if (prepare(orig_loc))
return NULL;
/*
Open input stream.
*/
- backup::String path(location);
- Input_stream *s= new Input_stream(*this, path);
+ Input_stream *s= new Input_stream(*this, backupdir, orig_loc);
m_stream= s;
if (!s)
@@ -576,7 +607,11 @@ Backup_restore_ctx::prepare_for_restore(
if (!s->open())
{
- fatal_error(ER_BACKUP_READ_LOC, path.ptr());
+ /*
+ For this error, use the actual value returned instead of the
+ path complimented with backupdir.
+ */
+ fatal_error(ER_BACKUP_READ_LOC, orig_loc.str);
return NULL;
}
=== modified file 'sql/backup/stream.cc'
--- a/sql/backup/stream.cc 2008-07-02 11:27:17 +0000
+++ b/sql/backup/stream.cc 2008-07-09 17:31:53 +0000
@@ -8,6 +8,10 @@
#define ZBUF_SIZE 65536 // compression I/O buffer size
#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+
const unsigned char backup_magic_bytes[8]=
{
0xE0, // ###.....
@@ -190,9 +194,30 @@ extern "C" int stream_read(void *instanc
}
-Stream::Stream(Logger &log, const ::String &name, int flags)
- :m_path(name), m_flags(flags), m_block_size(0), m_log(log)
+Stream::Stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc, int flags)
+ :m_flags(flags), m_block_size(0), m_log(log)
{
+ int path_len= 0;
+
+ /*
+ Prepare the path using the backupdir iff no path included
+ */
+ if (!test_if_hard_path(orig_loc.str))
+ {
+ path_len=backupdir->length() + orig_loc.length + 1;
+ m_path.alloc(path_len);
+ fn_format(m_path.c_ptr(), orig_loc.str, backupdir->c_ptr(), "",
+ MY_UNPACK_FILENAME);
+ }
+ else
+ {
+ path_len= orig_loc.length + 1;
+ m_path.alloc(path_len);
+ m_path.set_ascii(orig_loc.str, orig_loc.length);
+ }
+ m_path.length(path_len);
+
bzero(&stream, sizeof(stream));
bzero(&buf, sizeof(buf));
bzero(&mem, sizeof(mem));
@@ -228,9 +253,10 @@ bool Stream::rewind()
}
-Output_stream::Output_stream(Logger &log, const ::String &name,
+Output_stream::Output_stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc,
bool with_compression)
- :Stream(log, name, 0)
+ :Stream(log, backupdir, orig_loc, 0)
{
m_with_compression= with_compression;
stream.write= stream_write;
@@ -414,8 +440,9 @@ bool Output_stream::rewind()
}
-Input_stream::Input_stream(Logger &log, const ::String &name)
- :Stream(log, name, O_RDONLY)
+Input_stream::Input_stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc)
+ :Stream(log, backupdir, orig_loc, O_RDONLY)
{
m_with_compression= false;
stream.read= stream_read;
=== modified file 'sql/backup/stream.h'
--- a/sql/backup/stream.h 2008-06-26 16:20:30 +0000
+++ b/sql/backup/stream.h 2008-07-09 17:31:53 +0000
@@ -92,7 +92,7 @@ class Stream: public fd_stream
protected:
- Stream(Logger&, const ::String&, int);
+ Stream(Logger&, ::String *, LEX_STRING, int);
String m_path;
int m_flags; ///< flags used when opening the file
@@ -109,7 +109,7 @@ class Output_stream:
{
public:
- Output_stream(Logger&, const ::String&, bool);
+ Output_stream(Logger&, ::String *, LEX_STRING, bool);
bool open();
void close();
@@ -127,7 +127,7 @@ class Input_stream:
{
public:
- Input_stream(Logger&, const ::String &name);
+ Input_stream(Logger&, ::String *, LEX_STRING);
bool open();
void close();
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-07-01 20:32:27 +0000
+++ b/sql/mysqld.cc 2008-07-09 17:31:53 +0000
@@ -1362,6 +1362,7 @@ void clean_up(bool print_message)
my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(sys_var_backupdir.value, MYF(MY_ALLOW_ZERO_PTR));
free_tmpdir(&mysql_tmpdir_list);
#ifdef HAVE_REPLICATION
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
@@ -5745,6 +5746,8 @@ struct my_option my_long_options[] =
"Creating and dropping stored procedures alters ACLs. Disable with
--skip-automatic-sp-privileges.",
(uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges,
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"backupdir", 'B', "Path used to store backup data.", (uchar**)
&sys_var_backupdir.value,
+ (uchar**) &sys_var_backupdir.value, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"basedir", 'b',
"Path to installation directory. All paths are usually resolved relative to this.",
(uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR,
REQUIRED_ARG,
@@ -7853,6 +7856,21 @@ mysqld_get_one_option(int optid,
case 'l':
opt_log=1;
break;
+ case 'B':
+ {
+ /*
+ Check if directory exists and we have permission to create file and
+ write to file.
+ */
+ if (my_access(argument, (F_OK|W_OK)))
+ {
+ sql_print_warning("The path specified for the variable backupdir cannot"
+ " be accessed or is invalid. ref:'%s'\n", argument);
+ }
+ sys_var_backupdir.value= my_strdup(argument, MYF(0));
+ sys_var_backupdir.value_length= strlen(sys_var_backupdir.value);
+ break;
+ }
case 'h':
strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
/* Correct pointer set by my_getopt (for embedded library) */
@@ -8561,6 +8579,16 @@ static void fix_paths(void)
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
+
+ /*
+ Set backupdir if datadir set on command line but not otherwise set.
+ */
+ if (!sys_var_backupdir.value)
+ {
+ sys_var_backupdir.value= my_strdup(mysql_real_data_home, MYF(0));
+ sys_var_backupdir.value_length= strlen(mysql_real_data_home);
+ }
+
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
(void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
get_relative_path(PLUGINDIR), mysql_home);
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2008-05-27 19:47:15 +0000
+++ b/sql/set_var.cc 2008-07-09 17:31:53 +0000
@@ -149,6 +149,9 @@ static bool sys_update_general_log_path(
static void sys_default_general_log_path(THD *thd, enum_var_type type);
static bool sys_update_slow_log_path(THD *thd, set_var * var);
static void sys_default_slow_log_path(THD *thd, enum_var_type type);
+static int sys_check_backupdir(THD *thd, set_var *var);
+static bool sys_update_backupdir(THD *thd, set_var * var);
+static void sys_default_backupdir(THD *thd, enum_var_type type);
/*
Variable definition list
@@ -778,6 +781,15 @@ sys_var_str sys_var_slow_log_path(&vars,
opt_slow_logname);
static sys_var_log_output sys_var_log_output_state(&vars, "log_output",
&log_output_options,
&log_output_typelib, 0);
+
+/*
+ Create the backupdir dynamic variable.
+*/
+sys_var_str sys_var_backupdir(&vars, "backupdir",
+ sys_check_backupdir,
+ sys_update_backupdir,
+ sys_default_backupdir,
+ 0);
/*
@@ -2614,6 +2626,142 @@ uchar *sys_var_log_output::value_ptr(THD
return (uchar*) thd->strmake(tmp.ptr(), length);
}
+/*
+ Functions for backupdir variable.
+*/
+
+/**
+ Set the default for the backupdir
+
+ @param[IN] buff Buffer to use for making string.
+
+ @returns pointer to string (buff)
+*/
+char *make_default_backupdir(char *buff)
+{
+ strmake(buff, mysql_data_home, FN_REFLEN-5);
+ return buff;
+}
+
+/**
+ Check the backupdir value for validity.
+
+ This method ensures the users is specifying a valid path
+ for the backupdir. Validity in this case means the path
+ is accessible to the user.
+
+ @param[IN] thd Current thread context.
+ @param[IN] var The new value set in set_var structure.
+
+ @returns 0 valid, 1 invalid.
+*/
+static int sys_check_backupdir(THD *thd, set_var *var)
+{
+ char path[FN_REFLEN], buff[FN_REFLEN];
+ MY_STAT f_stat;
+ String str(buff, sizeof(buff), system_charset_info), *res;
+ const char *log_file_str;
+ size_t path_length;
+
+ if (!(res= var->value->val_str(&str)))
+ goto err;
+
+ log_file_str= res->c_ptr();
+ bzero(&f_stat, sizeof(MY_STAT));
+
+ /* Get dirname of the file path. */
+ (void) dirname_part(path, log_file_str, &path_length);
+
+ /* Dirname is empty if file path is relative. */
+ if (!path_length)
+ return 0;
+
+ /*
+ Check if directory exists and we have permission to create file and
+ write to file.
+ */
+ if (my_access(path, (F_OK|W_OK)))
+ goto err;
+
+ return 0;
+
+err:
+ my_error(ER_BACKUP_BACKUPDIR, MYF(0), var->value->str_value.c_ptr());
+ return 1;
+}
+
+/**
+ Update the backupdir variable
+
+ This method is used to change the backupdir variable.
+
+ @param[IN] thd Current thread context.
+ @param[IN] var The new value set in set_var structure.
+
+ @returns 0 valid, 1 invalid.
+*/
+static bool sys_update_backupdir(THD *thd, set_var * var)
+{
+ char buff[FN_REFLEN];
+ char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+ bool result= 0;
+ uint str_length= (var ? var->value->str_value.length() : 0);
+
+ if (!old_value)
+ {
+ old_value= make_default_backupdir(buff);
+ str_length= strlen(old_value);
+ }
+ if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
+ {
+ result= 1;
+ goto err;
+ }
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ logger.lock_exclusive();
+ old_value= sys_var_backupdir.value;
+ sys_var_backupdir.value= res;
+ sys_var_backupdir.value_length= str_length;
+ logger.unlock();
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+
+ if (my_access(sys_var_backupdir.value, (F_OK|W_OK)))
+ {
+ /*
+ There is a problem accessing backupdir specified. Revert to old
+ one and throw error.
+ */
+ if (old_value)
+ {
+ sys_var_backupdir.value= old_value;
+ sys_var_backupdir.value_length= strlen(old_value);
+ }
+ result= 1;
+ goto err;
+ }
+
+ return result;
+
+err:
+ my_error(ER_BACKUP_BACKUPDIR, MYF(0), var->value->str_value.c_ptr());
+ return result;
+}
+
+/**
+ Set the default value for the backupdir variable
+
+ This method is used to reset the backupdir variable to the
+ default by calling the update method without a path.
+
+ @param[IN] thd Current thread context.
+ @param[IN] type Ignored (needed for api).
+*/
+static void sys_default_backupdir(THD *thd, enum_var_type type)
+{
+ sys_update_backupdir(thd, 0);
+}
+
/*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET
=== modified file 'sql/set_var.h'
--- a/sql/set_var.h 2008-05-27 19:47:15 +0000
+++ b/sql/set_var.h 2008-07-09 17:31:53 +0000
@@ -1345,7 +1345,8 @@ CHARSET_INFO *get_old_charset_by_name(co
uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
NAMED_LIST **found);
-extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path;
+extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path,
+ sys_var_backupdir;
/* key_cache functions */
KEY_CACHE *get_key_cache(LEX_STRING *cache_name);
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2008-07-01 20:32:27 +0000
+++ b/sql/share/errmsg.txt 2008-07-09 17:31:53 +0000
@@ -6366,3 +6366,5 @@ ER_BACKUP_OBTAIN_NAME_LOCK_FAILED
ER_BACKUP_RELEASE_NAME_LOCK_FAILED
eng "Restore failed to release the name locks on the tables."
+ER_BACKUP_BACKUPDIR
+ eng "The path specified for the variable backupdir cannot be accessed or is invalid.
ref: %-.64s"
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-06-25 13:39:04 +0000
+++ b/sql/sql_parse.cc 2008-07-09 17:31:53 +0000
@@ -38,7 +38,7 @@
@defgroup Runtime_Environment Runtime Environment
@{
*/
-int execute_backup_command(THD*,LEX*);
+int execute_backup_command(THD*, LEX*, String*);
/* Used in error handling only */
#define SP_TYPE_STRING(LP) \
@@ -2168,10 +2168,21 @@ mysql_execute_command(THD *thd)
#else
{
/*
+ Create a string from the backupdir system variable and pass
+ to backup system.
+ */
+ String backupdir;
+
+ backupdir.alloc(sys_var_backupdir.value_length);
+ backupdir.set_ascii(sys_var_backupdir.value,
+ sys_var_backupdir.value_length);
+ backupdir.length(sys_var_backupdir.value_length);
+
+ /*
Note: execute_backup_command() sends a correct response to the client
(either ok, result set or error message).
- */
- if (execute_backup_command(thd,lex))
+ */
+ if (execute_backup_command(thd, lex, &backupdir))
goto error;
break;
}