diff options
author | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
---|---|---|
committer | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
commit | f4c589ff6c653d1d2a09c26e46ead3c8a15655d8 (patch) | |
tree | d253a359142dfc1ed247d5d4365d86972ea31109 /sql/sql_db.cc | |
parent | 7eec25e393727b16bb916b50d82b0aa3084e065c (diff) | |
download | mariadb-git-f4c589ff6c653d1d2a09c26e46ead3c8a15655d8.tar.gz |
Import changeset
Diffstat (limited to 'sql/sql_db.cc')
-rw-r--r-- | sql/sql_db.cc | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/sql/sql_db.cc b/sql/sql_db.cc new file mode 100644 index 00000000000..33c8ee54037 --- /dev/null +++ b/sql/sql_db.cc @@ -0,0 +1,300 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/* create and drop of databases */ + +#include "mysql_priv.h" +#include "sql_acl.h" +#include <my_dir.h> +#include <m_ctype.h> +#ifdef __WIN__ +#include <direct.h> +#endif + +static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, + uint level); + +void mysql_create_db(THD *thd, char *db, uint create_options) +{ + char path[FN_REFLEN+16]; + MY_DIR *dirp; + long result=1; + DBUG_ENTER("mysql_create_db"); + + if (!stripp_sp(db) || strlen(db) > NAME_LEN || check_db_name(db)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, db); + DBUG_VOID_RETURN; + } + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + + /* Check directory */ + (void)sprintf(path,"%s/%s", mysql_data_home, db); + unpack_dirname(path,path); // Convert if not unix + if ((dirp = my_dir(path,MYF(MY_DONT_SORT)))) + { + my_dirend(dirp); + if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) + { + net_printf(&thd->net,ER_DB_CREATE_EXISTS,db); + goto exit; + } + result = 0; + } + else + { + strend(path)[-1]=0; // Remove last '/' from path + if (my_mkdir(path,0777,MYF(0)) < 0) + { + net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno); + goto exit; + } + } + if (!thd->query) + { + thd->query = path; + thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- + path); + } + { + mysql_update_log.write(thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + } + if (thd->query == path) + { + thd->query = 0; // just in case + thd->query_length = 0; + } + send_ok(&thd->net, result); + +exit: + VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + DBUG_VOID_RETURN; +} + +const char *del_exts[]= +{".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".PSM",".MYI",".MYD", ".db", + NullS}; +static TYPELIB deletable_extentions= +{array_elements(del_exts)-1,"del_exts", del_exts}; + + +void mysql_rm_db(THD *thd,char *db,bool if_exists) +{ + long deleted=0; + char path[FN_REFLEN+16]; + MY_DIR *dirp; + DBUG_ENTER("mysql_rm_db"); + + if (!stripp_sp(db) || strlen(db) > NAME_LEN || check_db_name(db)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, db); + DBUG_VOID_RETURN; + } + + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + VOID(pthread_mutex_lock(&LOCK_open)); + + (void) sprintf(path,"%s/%s",mysql_data_home,db); + unpack_dirname(path,path); // Convert if not unix + /* See if the directory exists */ + if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT)))) + { + if (!if_exists) + net_printf(&thd->net,ER_DB_DROP_EXISTS,db); + else + send_ok(&thd->net,0); + goto exit; + } + remove_db_from_cache(db); + + if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0) + { + if (!thd->query) + { + thd->query = path; + thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)- + path); + } + mysql_update_log.write(thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + if (thd->query == path) + { + thd->query = 0; // just in case + thd->query_length = 0; + } + send_ok(&thd->net,(ulong) deleted); + } + +exit: + VOID(pthread_mutex_unlock(&LOCK_open)); + VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + DBUG_VOID_RETURN; +} + +/* + Removes files with known extensions plus all found subdirectories that + are 2 digits (raid directories). +*/ + +static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, + uint level) +{ + long deleted=0; + ulong found_other_files=0; + char filePath[FN_REFLEN]; + DBUG_ENTER("mysql_rm_known_files"); + DBUG_PRINT("enter",("path: %s", path)); + /* remove all files with known extensions */ + + for (uint idx=2 ; + idx < (uint) dirp->number_off_files && !thd->killed ; + idx++) + { + FILEINFO *file=dirp->dir_entry+idx; + DBUG_PRINT("info",("Examining: %s", file->name)); + + /* Check if file is a raid directory */ + if (isdigit(file->name[0]) && isdigit(file->name[1]) && + !file->name[2] && !level) + { + char newpath[FN_REFLEN]; + MY_DIR *new_dirp; + strxmov(newpath,path,"/",file->name,NullS); + if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) + { + DBUG_PRINT("my",("New subdir found: %s", newpath)); + if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0) + { + my_dirend(dirp); + DBUG_RETURN(-1); + } + } + continue; + } + if (find_type(fn_ext(file->name),&deletable_extentions,1) <= 0) + { + found_other_files++; + continue; + } + strxmov(filePath,path,"/",file->name,NullS); + if (my_delete(filePath,MYF(MY_WME))) + { + net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error); + my_dirend(dirp); + DBUG_RETURN(-1); + } + deleted++; + } + + my_dirend(dirp); + + if (thd->killed) + { + send_error(&thd->net,ER_SERVER_SHUTDOWN); + DBUG_RETURN(-1); + } + + /* + If the directory is a symbolic link, remove the link first, then + remove the directory the symbolic link pointed at + */ + if (!found_other_files) + { +#ifdef HAVE_READLINK + int linkcount = readlink(path,filePath,sizeof(filePath)-1); + if (linkcount > 0) // If the path was a symbolic link + { + *(filePath + linkcount) = '\0'; + if (my_delete(path,MYF(!level ? MY_WME : 0))) + { + /* Don't give errors if we can't delete 'RAID' directory */ + if (level) + DBUG_RETURN(deleted); + send_error(&thd->net); + DBUG_RETURN(-1); + } + path=filePath; + } +#endif + /* Don't give errors if we can't delete 'RAID' directory */ + if (rmdir(path) < 0 && !level) + { + net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno); + DBUG_RETURN(-1); + } + } + DBUG_RETURN(deleted); +} + + +bool mysql_change_db(THD *thd,const char *name) +{ + int length; + char *dbname=my_strdup((char*) name,MYF(MY_WME)); + char path[FN_REFLEN]; + uint db_access; + DBUG_ENTER("mysql_change_db"); + + if (!dbname || !(length=stripp_sp(dbname))) + { + x_free(dbname); /* purecov: inspected */ + send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ + } + if (length > NAME_LEN) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, dbname); + DBUG_RETURN(1); + } + DBUG_PRINT("general",("Use database: %s", dbname)); + if (test_all_bits(thd->master_access,DB_ACLS)) + db_access=DB_ACLS; + else + db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, + thd->priv_user,dbname) | + thd->master_access); + if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + { + net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + thd->priv_user, + thd->host ? thd->host : thd->ip ? thd->ip : "unknown", + dbname); + mysql_log.write(COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + thd->priv_user, + thd->host ? thd->host : thd->ip ? thd->ip : "unknown", + dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + + (void) sprintf(path,"%s/%s",mysql_data_home,dbname); + unpack_dirname(path,path); // Convert if not unix + if (access(path,F_OK)) + { + net_printf(&thd->net,ER_BAD_DB_ERROR,dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + send_ok(&thd->net); + x_free(thd->db); + thd->db=dbname; + thd->db_access=db_access; + DBUG_RETURN(0); +} |