Drizzled Public API Documentation

my_symlink2.cc
00001 /* Copyright (C) 2000 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /*
00017   Advanced symlink handling.
00018   This is used in MyISAM to let users symlinks tables to different disk.
00019   The main idea with these functions is to automaticly create, delete and
00020   rename files and symlinks like they would be one unit.
00021 */
00022 
00023 #include <config.h>
00024 
00025 #include <drizzled/internal/my_sys.h>
00026 #include <drizzled/error.h>
00027 #include <drizzled/internal/m_string.h>
00028 
00029 namespace drizzled
00030 {
00031 namespace internal
00032 {
00033 
00034 int my_create_with_symlink(const char *linkname, const char *filename,
00035                            int createflags, int access_flags, myf MyFlags)
00036 {
00037   int file;
00038   int tmp_errno;
00039   /* Test if we should create a link */
00040   int create_link;
00041   char abs_linkname[FN_REFLEN];
00042   char rp_buff[PATH_MAX];
00043 
00044   if (my_disable_symlinks)
00045   {
00046     /* Create only the file, not the link and file */
00047     create_link= 0;
00048     if (linkname)
00049       filename= linkname;
00050   }
00051   else
00052   {
00053     if (linkname)
00054     {
00055       if (!realpath(linkname,rp_buff))
00056         my_load_path(rp_buff, linkname, NULL);
00057       rp_buff[FN_REFLEN-1]= '\0';
00058       strcpy(abs_linkname,rp_buff);
00059     }
00060     create_link= (linkname && strcmp(abs_linkname,filename));
00061   }
00062 
00063   if (!(MyFlags & MY_DELETE_OLD))
00064   {
00065     if (!access(filename,F_OK))
00066     {
00067       errno= EEXIST;
00068       my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
00069       return(-1);
00070     }
00071     if (create_link && !access(linkname,F_OK))
00072     {
00073       errno= EEXIST;
00074       my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST);
00075       return(-1);
00076     }
00077   }
00078 
00079   if ((file=my_create(filename, createflags, access_flags, MyFlags)) >= 0)
00080   {
00081     if (create_link)
00082     {
00083       /* Delete old link/file */
00084       if (MyFlags & MY_DELETE_OLD)
00085   my_delete(linkname, MYF(0));
00086       /* Create link */
00087       if (symlink(filename,linkname))
00088       {
00089   /* Fail, remove everything we have done */
00090   tmp_errno=errno;
00091   my_close(file,MYF(0));
00092   my_delete(filename, MYF(0));
00093   file= -1;
00094   errno=tmp_errno;
00095       }
00096       else if (MyFlags & MY_SYNC_DIR)
00097         my_sync_dir_by_file(linkname, MyFlags);
00098     }
00099   }
00100   return(file);
00101 }
00102 
00103 /*
00104   If the file was a symlink, delete both symlink and the file which the
00105   symlink pointed to.
00106 */
00107 
00108 int my_delete_with_symlink(const char *name, myf MyFlags)
00109 {
00110   char link_name[FN_REFLEN];
00111   ssize_t sym_link_size= readlink(name,link_name,FN_REFLEN-1);
00112   int was_symlink= (!my_disable_symlinks && sym_link_size != -1);
00113   int result;
00114 
00115   if (!(result=my_delete(name, MyFlags)))
00116   {
00117     if (was_symlink)
00118     {
00119       link_name[sym_link_size]= '\0';
00120       result= my_delete(link_name, MyFlags);
00121     }
00122   }
00123   return(result);
00124 }
00125 
00126 /*
00127   If the file is a normal file, just rename it.
00128   If the file is a symlink:
00129    - Create a new file with the name 'to' that points at
00130      symlink_dir/basename(to)
00131    - Rename the symlinked file to symlink_dir/basename(to)
00132    - Delete 'from'
00133    If something goes wrong, restore everything.
00134 */
00135 
00136 int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
00137 {
00138   char link_name[FN_REFLEN], tmp_name[FN_REFLEN];
00139   int sym_link_size= -1;
00140   int was_symlink= (!my_disable_symlinks &&
00141                    (sym_link_size= static_cast<int>(readlink(from,link_name,
00142                                                     FN_REFLEN-1))) != -1); 
00143   int result=0;
00144   int name_is_different;
00145 
00146   if (!was_symlink)
00147     return(my_rename(from, to, MyFlags));
00148   else
00149     link_name[sym_link_size]= '\0';
00150 
00151   /* Change filename that symlink pointed to */
00152   strcpy(tmp_name, to);
00153   fn_same(tmp_name,link_name,1);    /* Copy dir */
00154   name_is_different= strcmp(link_name, tmp_name);
00155   if (name_is_different && !access(tmp_name, F_OK))
00156   {
00157     errno= EEXIST;
00158     if (MyFlags & MY_WME)
00159       my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST);
00160     return(1);
00161   }
00162 
00163   /* Create new symlink */
00164   if (symlink(tmp_name, to))
00165     return(1);
00166   else if (MyFlags & MY_SYNC_DIR)
00167     my_sync_dir_by_file(to, MyFlags);
00168 
00169   /*
00170     Rename symlinked file if the base name didn't change.
00171     This can happen if you use this function where 'from' and 'to' has
00172     the same basename and different directories.
00173    */
00174 
00175   if (name_is_different && my_rename(link_name, tmp_name, MyFlags))
00176   {
00177     int save_errno=errno;
00178     my_delete(to, MyFlags);     /* Remove created symlink */
00179     errno=save_errno;
00180     return(1);
00181   }
00182 
00183   /* Remove original symlink */
00184   if (my_delete(from, MyFlags))
00185   {
00186     int save_errno=errno;
00187     /* Remove created link */
00188     my_delete(to, MyFlags);
00189     /* Rename file back */
00190     if (strcmp(link_name, tmp_name))
00191       (void) my_rename(tmp_name, link_name, MyFlags);
00192     errno=save_errno;
00193     result= 1;
00194   }
00195   return(result);
00196 }
00197 
00198 } /* namespace internal */
00199 } /* namespace drizzled */