~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to mysys/my_symlink2.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}