~drizzle-trunk/drizzle/development

1 by brian
clean slate
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
994.2.4 by Monty Taylor
Blast. Fixed some make distcheck issues.
23
#include "mysys/mysys_priv.h"
24
#include "mysys/mysys_err.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
25
#include <mystrings/m_string.h>
1 by brian
clean slate
26
27
File my_create_with_symlink(const char *linkname, const char *filename,
28
			    int createflags, int access_flags, myf MyFlags)
29
{
30
  File file;
31
  int tmp_errno;
32
  /* Test if we should create a link */
33
  int create_link;
34
  char abs_linkname[FN_REFLEN];
1060.2.5 by Eric Lambert
-removed my_realpath from my_symlink and replaced it with calls to posix realpath
35
  char rp_buff[PATH_MAX];
1 by brian
clean slate
36
37
  if (my_disable_symlinks)
38
  {
39
    /* Create only the file, not the link and file */
40
    create_link= 0;
41
    if (linkname)
42
      filename= linkname;
43
  }
44
  else
45
  {
46
    if (linkname)
1060.2.5 by Eric Lambert
-removed my_realpath from my_symlink and replaced it with calls to posix realpath
47
    {
48
      if (!realpath(linkname,rp_buff))
49
        my_load_path(rp_buff, linkname, NULL);
50
      rp_buff[FN_REFLEN-1]= '\0';
51
      strcpy(abs_linkname,rp_buff);
52
    }
1 by brian
clean slate
53
    create_link= (linkname && strcmp(abs_linkname,filename));
54
  }
55
56
  if (!(MyFlags & MY_DELETE_OLD))
57
  {
58
    if (!access(filename,F_OK))
59
    {
60
      my_errno= errno= EEXIST;
61
      my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
62
      return(-1);
1 by brian
clean slate
63
    }
64
    if (create_link && !access(linkname,F_OK))
65
    {
66
      my_errno= errno= EEXIST;
67
      my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST);
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
68
      return(-1);
1 by brian
clean slate
69
    }
70
  }
71
72
  if ((file=my_create(filename, createflags, access_flags, MyFlags)) >= 0)
73
  {
74
    if (create_link)
75
    {
76
      /* Delete old link/file */
77
      if (MyFlags & MY_DELETE_OLD)
78
	my_delete(linkname, MYF(0));
79
      /* Create link */
1060.2.4 by Eric Lambert
-replaced my_symlink call with posix symlink call
80
      if (symlink(filename,linkname))
1 by brian
clean slate
81
      {
82
	/* Fail, remove everything we have done */
83
	tmp_errno=my_errno;
84
	my_close(file,MYF(0));
85
	my_delete(filename, MYF(0));
86
	file= -1;
87
	my_errno=tmp_errno;
88
      }
1060.2.4 by Eric Lambert
-replaced my_symlink call with posix symlink call
89
      else if (MyFlags & MY_SYNC_DIR)
90
        my_sync_dir_by_file(linkname, MyFlags);
1 by brian
clean slate
91
    }
92
  }
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
93
  return(file);
1 by brian
clean slate
94
}
95
96
/*
97
  If the file was a symlink, delete both symlink and the file which the
98
  symlink pointed to.
99
*/
100
101
int my_delete_with_symlink(const char *name, myf MyFlags)
102
{
103
  char link_name[FN_REFLEN];
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
104
  ssize_t sym_link_size= readlink(name,link_name,FN_REFLEN-1);
105
  int was_symlink= (!my_disable_symlinks && sym_link_size != -1);
1 by brian
clean slate
106
  int result;
107
108
  if (!(result=my_delete(name, MyFlags)))
109
  {
110
    if (was_symlink)
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
111
    {
112
      link_name[sym_link_size]= '\0';
113
      result= my_delete(link_name, MyFlags);
114
    }
1 by brian
clean slate
115
  }
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
116
  return(result);
1 by brian
clean slate
117
}
118
119
/*
120
  If the file is a normal file, just rename it.
121
  If the file is a symlink:
122
   - Create a new file with the name 'to' that points at
123
     symlink_dir/basename(to)
124
   - Rename the symlinked file to symlink_dir/basename(to)
125
   - Delete 'from'
126
   If something goes wrong, restore everything.
127
*/
128
129
int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
130
{
131
#ifndef HAVE_READLINK
132
  return my_rename(from, to, MyFlags);
133
#else
134
  char link_name[FN_REFLEN], tmp_name[FN_REFLEN];
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
135
  int sym_link_size= -1;
1 by brian
clean slate
136
  int was_symlink= (!my_disable_symlinks &&
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
137
                   (sym_link_size= readlink(from,link_name,FN_REFLEN-1)) != -1);
1 by brian
clean slate
138
  int result=0;
139
  int name_is_different;
140
141
  if (!was_symlink)
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
142
    return(my_rename(from, to, MyFlags));
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
143
  else
144
    link_name[sym_link_size]= '\0';
1 by brian
clean slate
145
146
  /* Change filename that symlink pointed to */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
147
  strcpy(tmp_name, to);
1 by brian
clean slate
148
  fn_same(tmp_name,link_name,1);		/* Copy dir */
149
  name_is_different= strcmp(link_name, tmp_name);
150
  if (name_is_different && !access(tmp_name, F_OK))
151
  {
152
    my_errno= EEXIST;
153
    if (MyFlags & MY_WME)
154
      my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST);
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
155
    return(1);
1 by brian
clean slate
156
  }
157
158
  /* Create new symlink */
1060.2.4 by Eric Lambert
-replaced my_symlink call with posix symlink call
159
  if (symlink(tmp_name, to))
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
160
    return(1);
1060.2.4 by Eric Lambert
-replaced my_symlink call with posix symlink call
161
  else if (MyFlags & MY_SYNC_DIR)
162
    my_sync_dir_by_file(to, MyFlags);
1 by brian
clean slate
163
164
  /*
165
    Rename symlinked file if the base name didn't change.
166
    This can happen if you use this function where 'from' and 'to' has
167
    the same basename and different directories.
168
   */
169
170
  if (name_is_different && my_rename(link_name, tmp_name, MyFlags))
171
  {
172
    int save_errno=my_errno;
173
    my_delete(to, MyFlags);			/* Remove created symlink */
174
    my_errno=save_errno;
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
175
    return(1);
1 by brian
clean slate
176
  }
177
178
  /* Remove original symlink */
179
  if (my_delete(from, MyFlags))
180
  {
181
    int save_errno=my_errno;
182
    /* Remove created link */
183
    my_delete(to, MyFlags);
184
    /* Rename file back */
185
    if (strcmp(link_name, tmp_name))
186
      (void) my_rename(tmp_name, link_name, MyFlags);
187
    my_errno=save_errno;
188
    result= 1;
189
  }
51.3.16 by Jay Pipes
Phase 4 removal of DBUG in mysys
190
  return(result);
1 by brian
clean slate
191
#endif /* HAVE_READLINK */
192
}