#At file:///d2/hf/mysql_common/60mrg/
2797 Alexey Botchkov 2008-08-24 [merge]
merging
modified:
include/my_sys.h
include/myisam.h
mysql-test/r/partition_symlink.result
mysql-test/t/partition_symlink.test
mysql-test/t/symlink.test
mysys/my_symlink.c
sql/mysql_priv.h
sql/mysqld.cc
sql/sql_parse.cc
storage/myisam/mi_check.c
storage/myisam/mi_open.c
storage/myisam/mi_static.c
storage/myisam/myisamchk.c
storage/myisam/myisamdef.h
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2008-08-21 05:20:27 +0000
+++ b/include/my_sys.h 2008-08-24 16:12:12 +0000
@@ -605,6 +605,7 @@ extern int my_close(File Filedes,myf MyF
extern File my_dup(File file, myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
extern int my_readlink(char *to, const char *filename, myf MyFlags);
+extern int my_is_symlink(const char *filename);
extern int my_realpath(char *to, const char *filename, myf MyFlags);
extern File my_create_with_symlink(const char *linkname, const char *filename,
int createflags, int access_flags,
=== modified file 'include/myisam.h'
--- a/include/myisam.h 2008-07-24 11:33:35 +0000
+++ b/include/myisam.h 2008-08-24 16:12:12 +0000
@@ -263,6 +263,10 @@ extern my_bool myisam_flush,myisam_delay
extern my_off_t myisam_max_temp_length;
extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size;
+/* usually used to check if a symlink points into the mysql data home */
+/* which is normally forbidden */
+extern int (*myisam_test_invalid_symlink)(const char *filename);
+
/* Prototypes for myisam-functions */
extern int mi_close(struct st_myisam_info *file);
=== modified file 'mysql-test/r/partition_symlink.result'
--- a/mysql-test/r/partition_symlink.result 2008-03-20 14:25:58 +0000
+++ b/mysql-test/r/partition_symlink.result 2008-08-24 16:12:12 +0000
@@ -113,9 +113,9 @@ set @@sql_mode=@org_mode;
create table t1 (a int)
partition by key (a)
(partition p0 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data');
-ERROR 42000: Incorrect table name 'part-data'
+ERROR HY000: Incorrect arguments to DATA DIRECTORY
create table t1 (a int)
partition by key (a)
(partition p0,
partition p1 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data');
-ERROR 42000: Incorrect table name 'part-data'
+ERROR HY000: Incorrect arguments to DATA DIRECTORY
=== modified file 'mysql-test/t/partition_symlink.test'
--- a/mysql-test/t/partition_symlink.test 2008-03-20 14:25:58 +0000
+++ b/mysql-test/t/partition_symlink.test 2008-08-24 16:12:12 +0000
@@ -154,7 +154,7 @@ set @@sql_mode=@org_mode;
#
# Bug 21350: Data Directory problems
#
--- error ER_WRONG_TABLE_NAME
+-- error ER_WRONG_ARGUMENTS
create table t1 (a int)
partition by key (a)
(partition p0 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data');
@@ -163,7 +163,7 @@ partition by key (a)
# Insert a test that manages to create the first partition and fails with
# the second, ensure that we clean up afterwards in a proper manner.
#
---error ER_WRONG_TABLE_NAME
+--error ER_WRONG_ARGUMENTS
create table t1 (a int)
partition by key (a)
(partition p0,
=== modified file 'mysql-test/t/symlink.test'
--- a/mysql-test/t/symlink.test 2008-04-05 10:27:12 +0000
+++ b/mysql-test/t/symlink.test 2008-08-24 16:12:12 +0000
@@ -65,7 +65,7 @@ drop table t1;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
SHOW CREATE TABLE t9;
---error 1103,1103
+--error 1103, 1103
create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp";
# Check that we cannot link over a table from another database.
@@ -75,7 +75,7 @@ create database mysqltest;
--error 1,1
create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
---error 1103,1103
+--error 1103, 1103
create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
# Should fail becasue the file t9.MYI already exist in 'run'
=== modified file 'mysys/my_symlink.c'
--- a/mysys/my_symlink.c 2008-04-28 16:24:05 +0000
+++ b/mysys/my_symlink.c 2008-08-24 16:12:12 +0000
@@ -108,38 +108,39 @@ int my_symlink(const char *content, cons
#define BUFF_LEN FN_LEN
#endif
+
+int my_is_symlink(const char *filename __attribute__((unused)))
+{
+ struct stat stat_buff;
+ return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
+}
+
+
int my_realpath(char *to, const char *filename,
myf MyFlags __attribute__((unused)))
{
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0;
char buff[BUFF_LEN];
- struct stat stat_buff;
+ char *ptr;
DBUG_ENTER("my_realpath");
- if (!(MyFlags & MY_RESOLVE_LINK) ||
- (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
- {
- char *ptr;
- DBUG_PRINT("info",("executing realpath"));
- if ((ptr=realpath(filename,buff)))
- {
+ DBUG_PRINT("info",("executing realpath"));
+ if ((ptr=realpath(filename,buff)))
strmake(to,ptr,FN_REFLEN-1);
- }
- else
- {
- /*
- Realpath didn't work; Use my_load_path() which is a poor substitute
- original name but will at least be able to resolve paths that starts
- with '.'.
- */
- DBUG_PRINT("error",("realpath failed with errno: %d", errno));
- my_errno=errno;
- if (MyFlags & MY_WME)
- my_error(EE_REALPATH, MYF(0), filename, my_errno);
- my_load_path(to, filename, NullS);
- result= -1;
- }
+ else
+ {
+ /*
+ Realpath didn't work; Use my_load_path() which is a poor substitute
+ original name but will at least be able to resolve paths that starts
+ with '.'.
+ */
+ DBUG_PRINT("error",("realpath failed with errno: %d", errno));
+ my_errno=errno;
+ if (MyFlags & MY_WME)
+ my_error(EE_REALPATH, MYF(0), filename, my_errno);
+ my_load_path(to, filename, NullS);
+ result= -1;
}
DBUG_RETURN(result);
#else
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-08-22 11:16:08 +0000
+++ b/sql/mysql_priv.h 2008-08-24 16:12:12 +0000
@@ -884,8 +884,6 @@ inline bool check_identifier_name(LEX_ST
return check_identifier_name(str, NAME_CHAR_LEN, 0, "");
}
-bool test_if_data_home_dir(const char *dir);
-
bool parse_sql(THD *thd,
Parser_state *parser_state,
Object_creation_ctx *creation_ctx);
@@ -1950,6 +1948,7 @@ extern CHARSET_INFO *character_set_files
#ifdef MYSQL_SERVER
extern char *opt_mysql_tmpdir, mysql_charsets_dir[],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
+extern int mysql_unpacked_real_data_home_len;
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
extern MY_TMPDIR mysql_tmpdir_list;
extern const LEX_STRING command_name[];
@@ -2589,6 +2588,8 @@ bool load_collation(MEM_ROOT *mem_root,
CHARSET_INFO **cl);
#endif /* MYSQL_SERVER */
+extern "C" int test_if_data_home_dir(const char *dir);
+
#endif /* MYSQL_CLIENT */
#endif /* MYSQL_PRIV_H */
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-08-16 15:22:47 +0000
+++ b/sql/mysqld.cc 2008-08-24 16:12:12 +0000
@@ -617,6 +617,7 @@ char mysql_real_data_home[FN_REFLEN],
*opt_init_file, *opt_tc_log_file,
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
char mysql_unpacked_real_data_home[FN_REFLEN];
+int mysql_unpacked_real_data_home_len;
uint reg_ext_length;
const key_map key_map_empty(0);
key_map key_map_full(0); // Will be initialized later
@@ -7662,6 +7663,7 @@ static void mysql_init_variables(void)
/* Things reset to zero */
opt_skip_slave_start= opt_reckless_slave = 0;
mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
+ myisam_test_invalid_symlink= test_if_data_home_dir;
opt_log= opt_slow_log= 0;
opt_update_log= 0;
log_output_options= find_bit_type(log_output_str, &log_output_typelib);
@@ -8623,9 +8625,12 @@ static void fix_paths(void)
pos[1]= 0;
}
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
- (void) fn_format(buff, mysql_real_data_home, "", "",
- (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
- (void) unpack_dirname(mysql_unpacked_real_data_home, buff);
+ my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
+ mysql_unpacked_real_data_home_len= strlen(mysql_unpacked_real_data_home);
+ if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
+ --mysql_unpacked_real_data_home_len;
+
+
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);
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-08-15 18:34:18 +0000
+++ b/sql/sql_parse.cc 2008-08-24 16:12:12 +0000
@@ -7689,11 +7689,12 @@ bool check_identifier_name(LEX_STRING *s
0 ok
1 error
*/
+C_MODE_START
-bool test_if_data_home_dir(const char *dir)
+int test_if_data_home_dir(const char *dir)
{
- char path[FN_REFLEN], conv_path[FN_REFLEN];
- uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home);
+ char path[FN_REFLEN];
+ uint dir_len;
DBUG_ENTER("test_if_data_home_dir");
if (!dir)
@@ -7701,24 +7702,30 @@ bool test_if_data_home_dir(const char *d
(void) fn_format(path, dir, "", "",
(MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
- dir_len= unpack_dirname(conv_path, dir);
-
- if (home_dir_len < dir_len)
+ dir_len= strlen(path);
+ if (mysql_unpacked_real_data_home_len<= dir_len)
{
+ if (dir_len > mysql_unpacked_real_data_home_len &&
+ path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR)
+ DBUG_RETURN(0);
+
if (lower_case_file_system)
{
- if (!my_strnncoll(character_set_filesystem,
- (const uchar*) conv_path, home_dir_len,
+ if (!my_strnncoll(default_charset_info, (const uchar*) path,
+ mysql_unpacked_real_data_home_len,
(const uchar*) mysql_unpacked_real_data_home,
- home_dir_len))
+ mysql_unpacked_real_data_home_len))
DBUG_RETURN(1);
}
- else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len))
+ else if (!memcmp(path, mysql_unpacked_real_data_home,
+ mysql_unpacked_real_data_home_len))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
+C_MODE_END
+
extern int MYSQLparse(void *thd); // from sql_yacc.cc
=== modified file 'storage/myisam/mi_check.c'
--- a/storage/myisam/mi_check.c 2008-08-15 11:43:08 +0000
+++ b/storage/myisam/mi_check.c 2008-08-24 16:12:12 +0000
@@ -1743,7 +1743,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- mi_open_datafile(info,share,-1))
+ mi_open_datafile(info,share,name,-1))
got_error=1;
}
}
@@ -2562,7 +2562,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- mi_open_datafile(info,share,-1))
+ mi_open_datafile(info,share,name,-1))
got_error=1;
}
}
@@ -3098,7 +3098,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- mi_open_datafile(info,share,-1))
+ mi_open_datafile(info,share,name,-1))
got_error=1;
}
}
=== modified file 'storage/myisam/mi_open.c'
--- a/storage/myisam/mi_open.c 2008-07-24 11:33:35 +0000
+++ b/storage/myisam/mi_open.c 2008-08-24 16:12:12 +0000
@@ -77,7 +77,7 @@ MI_INFO *test_if_reopen(char *filename)
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{
- int lock_error,kfile,open_mode,save_errno,have_rtree=0;
+ int lock_error,kfile,open_mode,save_errno,have_rtree=0, realpath_err;
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
key_parts,unique_key_parts,fulltext_keys,uniques;
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
@@ -103,8 +103,15 @@ MI_INFO *mi_open(const char *name, int m
and 'name_buff'. Don't change how name_buff is built without updating
myisam_backup::Backup::begin().
*/
- my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
- MY_UNPACK_FILENAME),MYF(0));
+ realpath_err= my_realpath(name_buff,
+ fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0));
+ if (my_is_symlink(org_name) &&
+ (realpath_err || (*myisam_test_invalid_symlink)(name_buff)))
+ {
+ my_errno= HA_WRONG_CREATE_OPTION;
+ DBUG_RETURN (NULL);
+ }
+
pthread_mutex_lock(&THR_LOCK_myisam);
if (!(old_info=test_if_reopen(name_buff)))
{
@@ -520,7 +527,7 @@ MI_INFO *mi_open(const char *name, int m
lock_error=1; /* Database unlocked */
}
- if (mi_open_datafile(&info, share, -1))
+ if (mi_open_datafile(&info, share, name, -1))
goto err;
errpos=5;
@@ -601,7 +608,7 @@ MI_INFO *mi_open(const char *name, int m
my_errno=EACCES; /* Can't open in write mode */
goto err;
}
- if (mi_open_datafile(&info, share, old_info->dfile))
+ if (mi_open_datafile(&info, share, name, old_info->dfile))
goto err;
errpos=5;
have_rtree= old_info->rtree_recursion_state != NULL;
@@ -1292,13 +1299,30 @@ The argument file_to_dup is here for the
exist a dup()-like call that would give us two different file descriptors.
*************************************************************************/
-int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
+int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name,
File file_to_dup __attribute__((unused)))
{
+ char *data_name= share->data_file_name;
+ char real_data_name[FN_REFLEN];
+
+ if (org_name)
+ {
+ fn_format(real_data_name,org_name,"",MI_NAME_DEXT,4);
+ if (my_is_symlink(real_data_name))
+ {
+ if (my_realpath(real_data_name, real_data_name, MYF(0)) ||
+ (*myisam_test_invalid_symlink)(real_data_name))
+ {
+ my_errno= HA_WRONG_CREATE_OPTION;
+ return 1;
+ }
+ data_name= real_data_name;
+ }
+ }
#ifdef USE_RAID
if (share->base.raid_type)
{
- info->dfile=my_raid_open(share->data_file_name,
+ info->dfile=my_raid_open(data_name,
share->mode | O_SHARE,
share->base.raid_type,
share->base.raid_chunks,
@@ -1307,8 +1331,7 @@ int mi_open_datafile(MI_INFO *info, MYIS
}
else
#endif
- info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
- MYF(MY_WME));
+ info->dfile=my_open(data_name, share->mode | O_SHARE, MYF(MY_WME));
return info->dfile >= 0 ? 0 : 1;
}
=== modified file 'storage/myisam/mi_static.c'
--- a/storage/myisam/mi_static.c 2008-05-09 10:27:23 +0000
+++ b/storage/myisam/mi_static.c 2008-08-24 16:12:12 +0000
@@ -43,6 +43,15 @@ my_off_t myisam_max_temp_length= MAX_FIL
ulong myisam_bulk_insert_tree_size=8192*1024;
ulong myisam_data_pointer_size=4;
+
+static int always_valid(const char *filename)
+{
+ return 0;
+}
+
+int (*myisam_test_invalid_symlink)(const char *filename)= always_valid;
+
+
/*
read_vec[] is used for converting between P_READ_KEY.. and SEARCH_
Position is , == , >= , <= , > , <
=== modified file 'storage/myisam/myisamchk.c'
--- a/storage/myisam/myisamchk.c 2008-07-09 07:12:43 +0000
+++ b/storage/myisam/myisamchk.c 2008-08-24 16:12:12 +0000
@@ -1030,7 +1030,7 @@ static int myisamchk(HA_CHECK *param, ch
error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks,
MYF(0));
- if (mi_open_datafile(info,info->s, -1))
+ if (mi_open_datafile(info,info->s, NULL, -1))
error=1;
param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
param->read_cache.file=info->dfile;
=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h 2008-07-09 08:19:03 +0000
+++ b/storage/myisam/myisamdef.h 2008-08-24 16:12:12 +0000
@@ -834,7 +834,9 @@ void mi_disable_non_unique_index(MI_INFO
extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where);
-int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
+int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name,
+ File file_to_dup);
+
int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (holyfoot:2797) | Alexey Botchkov | 24 Aug |