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 namespace internal {
00031 
00032 int my_create_with_symlink(const char *linkname, const char *filename,
00033                            int createflags, int access_flags, myf MyFlags)
00034 {
00035   /* Test if we should create a link */
00036   bool create_link= false;
00037   char rp_buff[PATH_MAX];
00038 
00039   if (my_disable_symlinks)
00040   {
00041     /* Create only the file, not the link and file */
00042     if (linkname)
00043       filename= linkname;
00044   }
00045   else if (linkname)
00046   {
00047     if (!realpath(linkname,rp_buff))
00048       my_load_path(rp_buff, linkname, NULL);
00049     rp_buff[FN_REFLEN-1]= '\0';
00050     char abs_linkname[FN_REFLEN];
00051     strcpy(abs_linkname, rp_buff);
00052     create_link= strcmp(abs_linkname, filename);
00053   }
00054 
00055   if (!(MyFlags & MY_DELETE_OLD))
00056   {
00057     if (!access(filename,F_OK))
00058     {
00059       errno= EEXIST;
00060       my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
00061       return(-1);
00062     }
00063     if (create_link && !access(linkname,F_OK))
00064     {
00065       errno= EEXIST;
00066       my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST);
00067       return(-1);
00068     }
00069   }
00070 
00071   int file= my_create(filename, createflags, access_flags, MyFlags);
00072   if (file >= 0 && create_link)
00073   {
00074     /* Delete old link/file */
00075     if (MyFlags & MY_DELETE_OLD)
00076       my_delete(linkname, MYF(0));
00077     /* Create link */
00078     if (symlink(filename,linkname))
00079     {
00080       /* Fail, remove everything we have done */
00081       int tmp_errno= errno;
00082       my_close(file, MYF(0));
00083       my_delete(filename, MYF(0));
00084       file= -1;
00085       errno= tmp_errno;
00086     }
00087     else if (MyFlags & MY_SYNC_DIR)
00088       my_sync_dir_by_file(linkname, MyFlags);
00089   }
00090   return file;
00091 }
00092 
00093 /*
00094   If the file was a symlink, delete both symlink and the file which the
00095   symlink pointed to.
00096 */
00097 
00098 int my_delete_with_symlink(const char *name, myf MyFlags)
00099 {
00100   char link_name[FN_REFLEN];
00101   ssize_t sym_link_size= readlink(name,link_name,FN_REFLEN-1);
00102   int was_symlink= (!my_disable_symlinks && sym_link_size != -1);
00103   int result;
00104 
00105   if (!(result=my_delete(name, MyFlags)))
00106   {
00107     if (was_symlink)
00108     {
00109       link_name[sym_link_size]= '\0';
00110       result= my_delete(link_name, MyFlags);
00111     }
00112   }
00113   return(result);
00114 }
00115 
00116 /*
00117   If the file is a normal file, just rename it.
00118   If the file is a symlink:
00119    - Create a new file with the name 'to' that points at
00120      symlink_dir/basename(to)
00121    - Rename the symlinked file to symlink_dir/basename(to)
00122    - Delete 'from'
00123    If something goes wrong, restore everything.
00124 */
00125 
00126 int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
00127 {
00128   char link_name[FN_REFLEN], tmp_name[FN_REFLEN];
00129   int sym_link_size= -1;
00130   int was_symlink= (!my_disable_symlinks &&
00131                    (sym_link_size= static_cast<int>(readlink(from,link_name,
00132                                                     FN_REFLEN-1))) != -1); 
00133   int result=0;
00134   int name_is_different;
00135 
00136   if (!was_symlink)
00137     return(my_rename(from, to, MyFlags));
00138   else
00139     link_name[sym_link_size]= '\0';
00140 
00141   /* Change filename that symlink pointed to */
00142   strcpy(tmp_name, to);
00143   fn_same(tmp_name,link_name,1);    /* Copy dir */
00144   name_is_different= strcmp(link_name, tmp_name);
00145   if (name_is_different && !access(tmp_name, F_OK))
00146   {
00147     errno= EEXIST;
00148     if (MyFlags & MY_WME)
00149       my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST);
00150     return 1;
00151   }
00152 
00153   /* Create new symlink */
00154   if (symlink(tmp_name, to))
00155     return 1;
00156   else if (MyFlags & MY_SYNC_DIR)
00157     my_sync_dir_by_file(to, MyFlags);
00158 
00159   /*
00160     Rename symlinked file if the base name didn't change.
00161     This can happen if you use this function where 'from' and 'to' has
00162     the same basename and different directories.
00163    */
00164 
00165   if (name_is_different && my_rename(link_name, tmp_name, MyFlags))
00166   {
00167     int save_errno=errno;
00168     my_delete(to, MyFlags);     /* Remove created symlink */
00169     errno=save_errno;
00170     return 1;
00171   }
00172 
00173   /* Remove original symlink */
00174   if (my_delete(from, MyFlags))
00175   {
00176     int save_errno=errno;
00177     /* Remove created link */
00178     my_delete(to, MyFlags);
00179     /* Rename file back */
00180     if (strcmp(link_name, tmp_name))
00181       (void) my_rename(tmp_name, link_name, MyFlags);
00182     errno=save_errno;
00183     result= 1;
00184   }
00185   return(result);
00186 }
00187 
00188 } /* namespace internal */
00189 } /* namespace drizzled */