diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2017-04-18 17:09:28 +0000 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-04-27 19:12:38 +0200 |
commit | ec68f764f6f9dc4028a0af93b78449e76e972b9a (patch) | |
tree | 7849247cb837fe86bd27e62fb6857bea1f4dc4b4 /client/mysqltest.cc | |
parent | 7bf409593e624deb00265e21e0d4579ce9fa7999 (diff) | |
download | mariadb-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.cc | 135 |
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 */ |