Drizzled Public API Documentation

my_symlink2.cc
1 /* Copyright (C) 2000 MySQL 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; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*
17  Advanced symlink handling.
18  This is used in MyISAM to let users symlinks tables to different disk.
19  The main idea with these functions is to automaticly create, delete and
20  rename files and symlinks like they would be one unit.
21 */
22 
23 #include <config.h>
24 
25 #include <drizzled/internal/my_sys.h>
26 #include <drizzled/error.h>
27 #include <drizzled/internal/m_string.h>
28 
29 namespace drizzled {
30 namespace internal {
31 
32 int my_create_with_symlink(const char *linkname, const char *filename,
33  int createflags, int access_flags, myf MyFlags)
34 {
35  /* Test if we should create a link */
36  bool create_link= false;
37 #ifndef __GNU__
38  char rp_buff[PATH_MAX];
39 #else
40  char *rp_buff = NULL;
41 #endif
42  if (my_disable_symlinks)
43  {
44  /* Create only the file, not the link and file */
45  if (linkname)
46  filename= linkname;
47  }
48  else if (linkname)
49  {
50  char abs_linkname[FN_REFLEN];
51 #ifndef __GNU__
52  if (!realpath(linkname,rp_buff))
53  my_load_path(rp_buff, linkname, NULL);
54  rp_buff[FN_REFLEN-1]= '\0';
55  strcpy(abs_linkname, rp_buff);
56 #else
57  // on hurd PATH_MAX isn't but realpath accept NULL and will malloc
58  rp_buff = realpath(linkname,NULL);
59  if (!rp_buff) {
60  char buffer[FN_REFLEN];
61  my_load_path(buffer, linkname, NULL);
62  buffer[FN_REFLEN-1]= '\0';
63  strcpy(abs_linkname,buffer);
64  } else {
65  if (strlen(rp_buff) >= FN_REFLEN) {
66  rp_buff[FN_REFLEN-1]= '\0';
67  }
68  strcpy(abs_linkname,rp_buff);
69  free(rp_buff);
70  }
71 #endif
72  create_link= strcmp(abs_linkname, filename);
73  }
74 
75  if (!(MyFlags & MY_DELETE_OLD))
76  {
77  if (!access(filename,F_OK))
78  {
79  errno= EEXIST;
80  my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
81  return(-1);
82  }
83  if (create_link && !access(linkname,F_OK))
84  {
85  errno= EEXIST;
86  my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST);
87  return(-1);
88  }
89  }
90 
91  int file= my_create(filename, createflags, access_flags, MyFlags);
92  if (file >= 0 && create_link)
93  {
94  /* Delete old link/file */
95  if (MyFlags & MY_DELETE_OLD)
96  my_delete(linkname, MYF(0));
97  /* Create link */
98  if (symlink(filename,linkname))
99  {
100  /* Fail, remove everything we have done */
101  int tmp_errno= errno;
102  my_close(file, MYF(0));
103  my_delete(filename, MYF(0));
104  file= -1;
105  errno= tmp_errno;
106  }
107  else if (MyFlags & MY_SYNC_DIR)
108  my_sync_dir_by_file(linkname, MyFlags);
109  }
110  return file;
111 }
112 
113 /*
114  If the file was a symlink, delete both symlink and the file which the
115  symlink pointed to.
116 */
117 
118 int my_delete_with_symlink(const char *name, myf MyFlags)
119 {
120  char link_name[FN_REFLEN];
121  ssize_t sym_link_size= readlink(name,link_name,FN_REFLEN-1);
122  int was_symlink= (!my_disable_symlinks && sym_link_size != -1);
123  int result;
124 
125  if (!(result=my_delete(name, MyFlags)))
126  {
127  if (was_symlink)
128  {
129  link_name[sym_link_size]= '\0';
130  result= my_delete(link_name, MyFlags);
131  }
132  }
133  return(result);
134 }
135 
136 /*
137  If the file is a normal file, just rename it.
138  If the file is a symlink:
139  - Create a new file with the name 'to' that points at
140  symlink_dir/basename(to)
141  - Rename the symlinked file to symlink_dir/basename(to)
142  - Delete 'from'
143  If something goes wrong, restore everything.
144 */
145 
146 int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
147 {
148  char link_name[FN_REFLEN], tmp_name[FN_REFLEN];
149  int sym_link_size= -1;
150  int was_symlink= (!my_disable_symlinks &&
151  (sym_link_size= static_cast<int>(readlink(from,link_name,
152  FN_REFLEN-1))) != -1);
153  int result=0;
154  int name_is_different;
155 
156  if (!was_symlink)
157  return(my_rename(from, to, MyFlags));
158  else
159  link_name[sym_link_size]= '\0';
160 
161  /* Change filename that symlink pointed to */
162  strcpy(tmp_name, to);
163  fn_same(tmp_name,link_name,1); /* Copy dir */
164  name_is_different= strcmp(link_name, tmp_name);
165  if (name_is_different && !access(tmp_name, F_OK))
166  {
167  errno= EEXIST;
168  if (MyFlags & MY_WME)
169  my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST);
170  return 1;
171  }
172 
173  /* Create new symlink */
174  if (symlink(tmp_name, to))
175  return 1;
176  else if (MyFlags & MY_SYNC_DIR)
177  my_sync_dir_by_file(to, MyFlags);
178 
179  /*
180  Rename symlinked file if the base name didn't change.
181  This can happen if you use this function where 'from' and 'to' has
182  the same basename and different directories.
183  */
184 
185  if (name_is_different && my_rename(link_name, tmp_name, MyFlags))
186  {
187  int save_errno=errno;
188  my_delete(to, MyFlags); /* Remove created symlink */
189  errno=save_errno;
190  return 1;
191  }
192 
193  /* Remove original symlink */
194  if (my_delete(from, MyFlags))
195  {
196  int save_errno=errno;
197  /* Remove created link */
198  my_delete(to, MyFlags);
199  /* Rename file back */
200  if (strcmp(link_name, tmp_name))
201  (void) my_rename(tmp_name, link_name, MyFlags);
202  errno=save_errno;
203  result= 1;
204  }
205  return(result);
206 }
207 
208 } /* namespace internal */
209 } /* namespace drizzled */
TODO: Rename this file - func.h is stupid.