sql_db.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* create and drop of databases */
  17. #include "mysql_priv.h"
  18. #include "sql_acl.h"
  19. #include <my_dir.h>
  20. #include <m_ctype.h>
  21. #ifdef __WIN__
  22. #include <direct.h>
  23. #endif
  24. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
  25.  uint level);
  26. /* db-name is already validated when we come here */
  27. void mysql_create_db(THD *thd, char *db, uint create_options)
  28. {
  29.   char  path[FN_REFLEN+16];
  30.   MY_DIR *dirp;
  31.   long result=1;
  32.   DBUG_ENTER("mysql_create_db");
  33.   
  34.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  35.   /* Check directory */
  36.   (void)sprintf(path,"%s/%s", mysql_data_home, db);
  37.   unpack_dirname(path,path); // Convert if not unix
  38.   if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
  39.   {
  40.     my_dirend(dirp);
  41.     if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
  42.     {
  43.       net_printf(&thd->net,ER_DB_CREATE_EXISTS,db);
  44.       goto exit;
  45.     }
  46.     result = 0;
  47.   }
  48.   else
  49.   {
  50.     strend(path)[-1]=0; // Remove last '/' from path
  51.     if (my_mkdir(path,0777,MYF(0)) < 0)
  52.     {
  53.       net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno);
  54.       goto exit;
  55.     }
  56.   }
  57.   if (!thd->query)
  58.   {
  59.     thd->query = path;
  60.     thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
  61. path);
  62.   }
  63.   {
  64.     mysql_update_log.write(thd,thd->query, thd->query_length);
  65.     if (mysql_bin_log.is_open())
  66.     {
  67.       Query_log_event qinfo(thd, thd->query);
  68.       mysql_bin_log.write(&qinfo);
  69.     }
  70.   }
  71.   if (thd->query == path)
  72.   {
  73.     thd->query = 0; // just in case
  74.     thd->query_length = 0;
  75.   }
  76.   send_ok(&thd->net, result);
  77. exit:
  78.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  79.   DBUG_VOID_RETURN;
  80. }
  81. const char *del_exts[]=
  82. {".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
  83. static TYPELIB deletable_extentions=
  84. {array_elements(del_exts)-1,"del_exts", del_exts};
  85. /* db-name is already validated when we come here */
  86. void mysql_rm_db(THD *thd,char *db,bool if_exists)
  87. {
  88.   long deleted=0;
  89.   char path[FN_REFLEN+16];
  90.   MY_DIR *dirp;
  91.   DBUG_ENTER("mysql_rm_db");
  92.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  93.   VOID(pthread_mutex_lock(&LOCK_open));
  94.   (void) sprintf(path,"%s/%s",mysql_data_home,db);
  95.   unpack_dirname(path,path); // Convert if not unix
  96.   /* See if the directory exists */
  97.   if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
  98.   {
  99.     if (!if_exists)
  100.       net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
  101.     else
  102.       send_ok(&thd->net,0);
  103.     goto exit;
  104.   }
  105.   remove_db_from_cache(db);
  106.   if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0)
  107.   {
  108.     if (!thd->query)
  109.     {
  110.       thd->query = path;
  111.       thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
  112.   path);
  113.     }
  114.     mysql_update_log.write(thd, thd->query, thd->query_length);
  115.     if (mysql_bin_log.is_open())
  116.     {
  117.       Query_log_event qinfo(thd, thd->query);
  118.       mysql_bin_log.write(&qinfo);
  119.     }
  120.     if (thd->query == path)
  121.     {
  122.       thd->query = 0; // just in case
  123.       thd->query_length = 0;
  124.     }
  125.     send_ok(&thd->net,(ulong) deleted);
  126.   }
  127. exit:
  128.   VOID(pthread_mutex_unlock(&LOCK_open));
  129.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  130.   DBUG_VOID_RETURN;
  131. }
  132. /*
  133.   Removes files with known extensions plus all found subdirectories that
  134.   are 2 digits (raid directories).
  135. */
  136. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
  137.  uint level)
  138. {
  139.   long deleted=0;
  140.   ulong found_other_files=0;
  141.   char filePath[FN_REFLEN];
  142.   DBUG_ENTER("mysql_rm_known_files");
  143.   DBUG_PRINT("enter",("path: %s", org_path));
  144.   /* remove all files with known extensions */
  145.   for (uint idx=2 ;
  146.        idx < (uint) dirp->number_off_files && !thd->killed ;
  147.        idx++)
  148.   {
  149.     FILEINFO *file=dirp->dir_entry+idx;
  150.     DBUG_PRINT("info",("Examining: %s", file->name));
  151.     /* Check if file is a raid directory */
  152.     if (isdigit(file->name[0]) && isdigit(file->name[1]) &&
  153. !file->name[2] && !level)
  154.     {
  155.       char newpath[FN_REFLEN];
  156.       MY_DIR *new_dirp;
  157.       strxmov(newpath,org_path,"/",file->name,NullS);
  158.       unpack_filename(newpath,newpath);
  159.       if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
  160.       {
  161. DBUG_PRINT("my",("New subdir found: %s", newpath));
  162. if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0)
  163. {
  164.   my_dirend(dirp);
  165.   DBUG_RETURN(-1);
  166. }
  167.       }
  168.       continue;
  169.     }
  170.     if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
  171.     {
  172.       found_other_files++;
  173.       continue;
  174.     }
  175.     strxmov(filePath,org_path,"/",file->name,NullS);
  176.     unpack_filename(filePath,filePath);
  177.     if (my_delete(filePath,MYF(MY_WME)))
  178.     {
  179.       net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
  180.       my_dirend(dirp);
  181.       DBUG_RETURN(-1);
  182.     }
  183.     deleted++;
  184.   }
  185.   my_dirend(dirp);
  186.   if (thd->killed)
  187.   {
  188.     send_error(&thd->net,ER_SERVER_SHUTDOWN);
  189.     DBUG_RETURN(-1);
  190.   }
  191.   /*
  192.     If the directory is a symbolic link, remove the link first, then
  193.     remove the directory the symbolic link pointed at
  194.   */
  195.   if (!found_other_files)
  196.   {
  197.     char tmp_path[FN_REFLEN];
  198.     char *path=unpack_filename(tmp_path,org_path);
  199. #ifdef HAVE_READLINK
  200.     int linkcount = readlink(path,filePath,sizeof(filePath)-1);
  201.     if (linkcount > 0) // If the path was a symbolic link
  202.     {
  203.       *(filePath + linkcount) = '';
  204.       if (my_delete(path,MYF(!level ? MY_WME : 0)))
  205.       {
  206. /* Don't give errors if we can't delete 'RAID' directory */
  207. if (level)
  208.   DBUG_RETURN(deleted);
  209. send_error(&thd->net);
  210. DBUG_RETURN(-1);
  211.       }
  212.       path=filePath;
  213.     }
  214. #endif
  215.     /* Remove last FN_LIBCHAR to not cause a probelm on OS/2 */
  216.     char *pos=strend(path);
  217.     if (pos > path && pos[-1] == FN_LIBCHAR)
  218.       *--pos=0;
  219.     /* Don't give errors if we can't delete 'RAID' directory */
  220.     if (rmdir(path) < 0 && !level)
  221.     {
  222.       net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
  223.       DBUG_RETURN(-1);
  224.     }
  225.   }
  226.   DBUG_RETURN(deleted);
  227. }
  228. bool mysql_change_db(THD *thd,const char *name)
  229. {
  230.   int length;
  231.   char *dbname=my_strdup((char*) name,MYF(MY_WME));
  232.   char path[FN_REFLEN];
  233.   uint db_access;
  234.   DBUG_ENTER("mysql_change_db");
  235.   if (!dbname || !(length=stripp_sp(dbname)))
  236.   {
  237.     x_free(dbname); /* purecov: inspected */
  238.     send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
  239.     DBUG_RETURN(1); /* purecov: inspected */
  240.   }
  241.   if (length > NAME_LEN)
  242.   {
  243.     net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
  244.     DBUG_RETURN(1);
  245.   }
  246.   DBUG_PRINT("general",("Use database: %s", dbname));
  247.   if (test_all_bits(thd->master_access,DB_ACLS))
  248.     db_access=DB_ACLS;
  249.   else
  250.     db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
  251. thd->priv_user,dbname) |
  252. thd->master_access);
  253.   if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  254.   {
  255.     net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
  256.        thd->priv_user,
  257.        thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
  258.        dbname);
  259.     mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
  260.     thd->priv_user,
  261.     thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
  262.     dbname);
  263.     my_free(dbname,MYF(0));
  264.     DBUG_RETURN(1);
  265.   }
  266.   (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
  267.   unpack_dirname(path,path); // Convert if not unix
  268.   if (access(path,F_OK))
  269.   {
  270.     net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
  271.     my_free(dbname,MYF(0));
  272.     DBUG_RETURN(1);
  273.   }
  274.   send_ok(&thd->net);
  275.   x_free(thd->db);
  276.   thd->db=dbname;
  277.   thd->db_access=db_access;
  278.   DBUG_RETURN(0);
  279. }