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