home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / sql_db.cpp < prev    next >
C/C++ Source or Header  |  2000-09-26  |  8KB  |  306 lines

  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.  
  17.  
  18. /* create and drop of databases */
  19.  
  20. #include "mysql_priv.h"
  21. #include "sql_acl.h"
  22. #include <my_dir.h>
  23. #include <m_ctype.h>
  24. #ifdef __WIN__
  25. #include <direct.h>
  26. #endif
  27.  
  28. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
  29.                  uint level);
  30.  
  31. void mysql_create_db(THD *thd, char *db, uint create_options)
  32. {
  33.   char     path[FN_REFLEN+16];
  34.   MY_DIR *dirp;
  35.   long result=1;
  36.   DBUG_ENTER("mysql_create_db");
  37.   
  38.   if (!stripp_sp(db) || strlen(db) > NAME_LEN || check_db_name(db))
  39.   {
  40.     net_printf(&thd->net,ER_WRONG_DB_NAME, db);
  41.     DBUG_VOID_RETURN;
  42.   }
  43.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  44.  
  45.   /* Check directory */
  46.   (void)sprintf(path,"%s/%s", mysql_data_home, db);
  47.   unpack_dirname(path,path);            // Convert if not unix
  48.   if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
  49.   {
  50.     my_dirend(dirp);
  51.     if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
  52.     {
  53.       net_printf(&thd->net,ER_DB_CREATE_EXISTS,db);
  54.       goto exit;
  55.     }
  56.     result = 0;
  57.   }
  58.   else
  59.   {
  60.     strend(path)[-1]=0;                // Remove last '/' from path
  61.     if (my_mkdir(path,0777,MYF(0)) < 0)
  62.     {
  63.       net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno);
  64.       goto exit;
  65.     }
  66.   }
  67.   if (!thd->query)
  68.   {
  69.     thd->query = path;
  70.     thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
  71.                 path);
  72.   }
  73.   {
  74.     mysql_update_log.write(thd,thd->query, thd->query_length);
  75.     if (mysql_bin_log.is_open())
  76.     {
  77.       Query_log_event qinfo(thd, thd->query);
  78.       mysql_bin_log.write(&qinfo);
  79.     }
  80.   }
  81.   if (thd->query == path)
  82.   {
  83.     thd->query = 0; // just in case
  84.     thd->query_length = 0;
  85.   }
  86.   send_ok(&thd->net, result);
  87.  
  88. exit:
  89.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  90.   DBUG_VOID_RETURN;
  91. }
  92.  
  93. const char *del_exts[]=
  94. {".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
  95. static TYPELIB deletable_extentions=
  96. {array_elements(del_exts)-1,"del_exts", del_exts};
  97.  
  98.  
  99. void mysql_rm_db(THD *thd,char *db,bool if_exists)
  100. {
  101.   long deleted=0;
  102.   char    path[FN_REFLEN+16];
  103.   MY_DIR *dirp;
  104.   DBUG_ENTER("mysql_rm_db");
  105.  
  106.   if (!stripp_sp(db) || strlen(db) > NAME_LEN || check_db_name(db))
  107.   {
  108.     net_printf(&thd->net,ER_WRONG_DB_NAME, db);
  109.     DBUG_VOID_RETURN;
  110.   }
  111.   
  112.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  113.   VOID(pthread_mutex_lock(&LOCK_open));
  114.  
  115.   (void) sprintf(path,"%s/%s",mysql_data_home,db);
  116.   unpack_dirname(path,path);            // Convert if not unix
  117.   /* See if the directory exists */
  118.   if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
  119.   {
  120.     if (!if_exists)
  121.       net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
  122.     else
  123.       send_ok(&thd->net,0);
  124.     goto exit;
  125.   }
  126.   remove_db_from_cache(db);
  127.  
  128.   if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0)
  129.   {
  130.     if (!thd->query)
  131.     {
  132.       thd->query = path;
  133.       thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
  134.                   path);
  135.     }
  136.     mysql_update_log.write(thd, thd->query, thd->query_length);
  137.     if (mysql_bin_log.is_open())
  138.     {
  139.       Query_log_event qinfo(thd, thd->query);
  140.       mysql_bin_log.write(&qinfo);
  141.     }
  142.     if (thd->query == path)
  143.     {
  144.       thd->query = 0; // just in case
  145.       thd->query_length = 0;
  146.     }
  147.     send_ok(&thd->net,(ulong) deleted);
  148.   }
  149.  
  150. exit:
  151.   VOID(pthread_mutex_unlock(&LOCK_open));
  152.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  153.   DBUG_VOID_RETURN;
  154. }
  155.  
  156. /*
  157.   Removes files with known extensions plus all found subdirectories that
  158.   are 2 digits (raid directories).
  159. */
  160.  
  161. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
  162.                   uint level)
  163. {
  164.   long deleted=0;
  165.   ulong found_other_files=0;
  166.   char filePath[FN_REFLEN];
  167.   DBUG_ENTER("mysql_rm_known_files");
  168.   DBUG_PRINT("enter",("path: %s", path));
  169.   /* remove all files with known extensions */
  170.  
  171.   for (uint idx=2 ;
  172.        idx < (uint) dirp->number_off_files && !thd->killed ;
  173.        idx++)
  174.   {
  175.     FILEINFO *file=dirp->dir_entry+idx;
  176.     DBUG_PRINT("info",("Examining: %s", file->name));
  177.  
  178.     /* Check if file is a raid directory */
  179.     if (isdigit(file->name[0]) && isdigit(file->name[1]) &&
  180.     !file->name[2] && !level)
  181.     {
  182.       char newpath[FN_REFLEN];
  183.       MY_DIR *new_dirp;
  184.       strxmov(newpath,path,"/",file->name,NullS);
  185.       if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
  186.       {
  187.     DBUG_PRINT("my",("New subdir found: %s", newpath));
  188.     if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0)
  189.     {
  190.       my_dirend(dirp);
  191.       DBUG_RETURN(-1);
  192.     }
  193.       }
  194.       continue;
  195.     }
  196.     if (find_type(fn_ext(file->name),&deletable_extentions,1) <= 0)
  197.     {
  198.       found_other_files++;
  199.       continue;
  200.     }
  201.     strxmov(filePath,path,"/",file->name,NullS);
  202.     if (my_delete(filePath,MYF(MY_WME)))
  203.     {
  204.       net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
  205.       my_dirend(dirp);
  206.       DBUG_RETURN(-1);
  207.     }
  208.     deleted++;
  209.   }
  210.  
  211.   my_dirend(dirp);
  212.  
  213.   if (thd->killed)
  214.   {
  215.     send_error(&thd->net,ER_SERVER_SHUTDOWN);
  216.     DBUG_RETURN(-1);
  217.   }
  218.  
  219.   /*
  220.     If the directory is a symbolic link, remove the link first, then
  221.     remove the directory the symbolic link pointed at
  222.   */
  223.   if (!found_other_files)
  224.   {
  225. #ifdef HAVE_READLINK
  226.     int linkcount = readlink(path,filePath,sizeof(filePath)-1);
  227.     if (linkcount > 0)            // If the path was a symbolic link
  228.     {
  229.       *(filePath + linkcount) = '\0';
  230.       if (my_delete(path,MYF(!level ? MY_WME : 0)))
  231.       {
  232.     /* Don't give errors if we can't delete 'RAID' directory */
  233.     if (level)
  234.       DBUG_RETURN(deleted);
  235.     send_error(&thd->net);
  236.     DBUG_RETURN(-1);
  237.       }
  238.       path=filePath;
  239.     }
  240. #endif
  241.     /* Don't give errors if we can't delete 'RAID' directory */
  242.     if (rmdir(path) < 0 && !level)
  243.     {
  244.       net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
  245.       DBUG_RETURN(-1);
  246.     }
  247.   }
  248.   DBUG_RETURN(deleted);
  249. }
  250.  
  251.  
  252. bool mysql_change_db(THD *thd,const char *name)
  253. {
  254.   int length;
  255.   char *dbname=my_strdup((char*) name,MYF(MY_WME));
  256.   char    path[FN_REFLEN];
  257.   uint db_access;
  258.   DBUG_ENTER("mysql_change_db");
  259.  
  260.   if (!dbname || !(length=stripp_sp(dbname)))
  261.   {
  262.     x_free(dbname);                /* purecov: inspected */
  263.     send_error(&thd->net,ER_NO_DB_ERROR);    /* purecov: inspected */
  264.     DBUG_RETURN(1);                /* purecov: inspected */
  265.   }
  266.   if (length > NAME_LEN)
  267.   {
  268.     net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
  269.     DBUG_RETURN(1);
  270.   }
  271.   DBUG_PRINT("general",("Use database: %s", dbname));
  272.   if (test_all_bits(thd->master_access,DB_ACLS))
  273.     db_access=DB_ACLS;
  274.   else
  275.     db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
  276.             thd->priv_user,dbname) |
  277.         thd->master_access);
  278.   if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  279.   {
  280.     net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
  281.            thd->priv_user,
  282.            thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
  283.            dbname);
  284.     mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
  285.             thd->priv_user,
  286.             thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
  287.             dbname);
  288.     my_free(dbname,MYF(0));
  289.     DBUG_RETURN(1);
  290.   }
  291.  
  292.   (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
  293.   unpack_dirname(path,path);            // Convert if not unix
  294.   if (access(path,F_OK))
  295.   {
  296.     net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
  297.     my_free(dbname,MYF(0));
  298.     DBUG_RETURN(1);
  299.   }
  300.   send_ok(&thd->net);
  301.   x_free(thd->db);
  302.   thd->db=dbname;
  303.   thd->db_access=db_access;
  304.   DBUG_RETURN(0);
  305. }
  306.