summaryrefslogtreecommitdiff
path: root/client/mysqltest.cc
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2017-04-18 17:09:28 +0000
committerSergei Golubchik <serg@mariadb.org>2017-04-27 19:12:38 +0200
commitec68f764f6f9dc4028a0af93b78449e76e972b9a (patch)
tree7849247cb837fe86bd27e62fb6857bea1f4dc4b4 /client/mysqltest.cc
parent7bf409593e624deb00265e21e0d4579ce9fa7999 (diff)
downloadmariadb-git-ec68f764f6f9dc4028a0af93b78449e76e972b9a.tar.gz
MDEV-9566 prepare mysqltest for mariabackup
- Do not throw output of exec command, if disable_result_log is set save and dump it if exec fails. Need tha to meaningfully analyze errors from mariabackup. - rmdir now removes the entire tree. need that because xtrabackup tests clean the whole directory. - all filesystem modifying commands now require the argument to be under MYSQLTEST_VARDIR or MYSQL_TMP_DIR.
Diffstat (limited to 'client/mysqltest.cc')
-rw-r--r--client/mysqltest.cc135
1 files changed, 119 insertions, 16 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 2673db0e469..492411d49ca 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -3373,6 +3373,12 @@ void do_exec(struct st_command *command)
#endif
#endif
+ if (disable_result_log)
+ {
+ /* Collect stderr output as well, for the case app. crashes or returns error.*/
+ dynstr_append(&ds_cmd, " 2>&1");
+ }
+
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -3408,16 +3414,7 @@ void do_exec(struct st_command *command)
len--;
}
#endif
- if (disable_result_log)
- {
- if (len)
- buf[len-1] = 0;
- DBUG_PRINT("exec_result",("%s", buf));
- }
- else
- {
- replace_dynstr_append_mem(ds_result, buf, len);
- }
+ replace_dynstr_append_mem(ds_result, buf, len);
}
error= pclose(res_file);
@@ -3427,7 +3424,7 @@ void do_exec(struct st_command *command)
dynstr_free(&ds_sorted);
}
- if (error > 0)
+ if (error)
{
uint status= WEXITSTATUS(error);
int i;
@@ -3473,6 +3470,12 @@ void do_exec(struct st_command *command)
}
dynstr_free(&ds_cmd);
+
+ if (disable_result_log)
+ {
+ /* Disable output in case of successful exit.*/
+ dynstr_set(&ds_res,"");
+ }
DBUG_VOID_RETURN;
}
@@ -3610,6 +3613,37 @@ void do_system(struct st_command *command)
}
+/* returns TRUE if path is inside a sandbox */
+bool is_sub_path(const char *path, size_t plen, const char *sandbox)
+{
+ size_t len= strlen(sandbox);
+ if (!sandbox || !len || plen <= len || memcmp(path, sandbox, len - 1)
+ || path[len] != '/')
+ return false;
+ return true;
+}
+
+
+/* returns TRUE if path cannot be modified */
+bool bad_path(const char *path)
+{
+ size_t plen= strlen(path);
+
+ const char *vardir= getenv("MYSQLTEST_VARDIR");
+ if (is_sub_path(path, plen, vardir))
+ return false;
+
+ const char *tmpdir= getenv("MYSQL_TMP_DIR");
+ if (is_sub_path(path, plen, tmpdir))
+ return false;
+
+ report_or_die("Path '%s' is not a subdirectory of MYSQLTEST_VARDIR '%s'"
+ "or MYSQL_TMP_DIR '%s'",
+ path, vardir, tmpdir);
+ return true;
+}
+
+
/*
SYNOPSIS
set_wild_chars
@@ -3668,6 +3702,9 @@ void do_remove_file(struct st_command *command)
rm_args, sizeof(rm_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
error= my_delete(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@@ -3711,6 +3748,9 @@ void do_remove_files_wildcard(struct st_command *command)
' ');
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
+ if (bad_path(ds_directory.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("listing directory: %s", dirname));
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
@@ -3785,6 +3825,9 @@ void do_copy_file(struct st_command *command)
sizeof(copy_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_to_file.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
/* MY_HOLD_ORIGINAL_MODES prevents attempts to chown the file */
error= (my_copy(ds_from_file.str, ds_to_file.str,
@@ -3822,6 +3865,9 @@ void do_move_file(struct st_command *command)
sizeof(move_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_to_file.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("Move %s to %s", ds_from_file.str, ds_to_file.str));
error= (my_rename(ds_from_file.str, ds_to_file.str,
MYF(disable_warnings ? 0 : MY_WME)) != 0);
@@ -3860,6 +3906,9 @@ void do_chmod_file(struct st_command *command)
sizeof(chmod_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_file.str))
+ DBUG_VOID_RETURN;
+
/* Parse what mode to set */
if (ds_mode.length != 4 ||
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
@@ -3931,6 +3980,9 @@ void do_mkdir(struct st_command *command)
mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_dirname.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
handle_command_error(command, error, my_errno);
@@ -3938,6 +3990,47 @@ void do_mkdir(struct st_command *command)
DBUG_VOID_RETURN;
}
+
+/*
+ Remove directory recursively.
+*/
+static int rmtree(const char *dir)
+{
+ char path[FN_REFLEN];
+ char sep[]={ FN_LIBCHAR, 0 };
+ int err=0;
+
+ MY_DIR *dir_info= my_dir(dir, MYF(MY_DONT_SORT | MY_WANT_STAT));
+ if (!dir_info)
+ return 1;
+
+ for (uint i= 0; i < dir_info->number_of_files; i++)
+ {
+ FILEINFO *file= dir_info->dir_entry + i;
+ /* Skip "." and ".." */
+ if (!strcmp(file->name, ".") || !strcmp(file->name, ".."))
+ continue;
+
+ strxnmov(path, sizeof(path), dir, sep, file->name, NULL);
+
+ if (!MY_S_ISDIR(file->mystat->st_mode))
+ err= my_delete(path, 0);
+ else
+ err= rmtree(path);
+
+ if(err)
+ break;
+ }
+
+ my_dirend(dir_info);
+
+ if (!err)
+ err= rmdir(dir);
+
+ return err;
+}
+
+
/*
SYNOPSIS
do_rmdir
@@ -3945,12 +4038,11 @@ void do_mkdir(struct st_command *command)
DESCRIPTION
rmdir <dir_name>
- Remove the empty directory <dir_name>
+ Remove the directory tree
*/
void do_rmdir(struct st_command *command)
{
- int error;
static DYNAMIC_STRING ds_dirname;
const struct command_arg rmdir_args[] = {
{ "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
@@ -3961,9 +4053,13 @@ void do_rmdir(struct st_command *command)
rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_dirname.str))
+ DBUG_VOID_RETURN;
+
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
- error= rmdir(ds_dirname.str) != 0;
- handle_command_error(command, error, errno);
+ if (rmtree(ds_dirname.str))
+ handle_command_error(command, 1, errno);
+
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -4076,6 +4172,9 @@ static void do_list_files_write_file_command(struct st_command *command,
list_files_args,
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
init_dynamic_string(&ds_content, "", 1024, 1024);
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
handle_command_error(command, error, my_errno);
@@ -4127,7 +4226,8 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
while (1)
{
c= my_getc(cur_file->file);
-
+ if (c == '\r')
+ c= my_getc(cur_file->file);
if (c == '\n')
{
cur_file->lineno++;
@@ -4178,6 +4278,9 @@ void do_write_file_command(struct st_command *command, my_bool append)
sizeof(write_file_args)/sizeof(struct command_arg),
' ');
+ if (bad_path(ds_filename.str))
+ DBUG_VOID_RETURN;
+
if (!append && access(ds_filename.str, F_OK) == 0)
{
/* The file should not be overwritten */