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