MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_symlink.c
1 /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
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 #include "mysys_priv.h"
17 #include "mysys_err.h"
18 #include <m_string.h>
19 #include <errno.h>
20 #ifdef HAVE_REALPATH
21 #include <sys/param.h>
22 #include <sys/stat.h>
23 #endif
24 
25 /*
26  Reads the content of a symbolic link
27  If the file is not a symbolic link, return the original file name in to.
28 
29  RETURN
30  0 If filename was a symlink, (to will be set to value of symlink)
31  1 If filename was a normal file (to will be set to filename)
32  -1 on error.
33 */
34 
35 int my_readlink(char *to, const char *filename, myf MyFlags)
36 {
37 #ifndef HAVE_READLINK
38  strmov(to,filename);
39  return 1;
40 #else
41  int result=0;
42  int length;
43  DBUG_ENTER("my_readlink");
44 
45  if ((length=readlink(filename, to, FN_REFLEN-1)) < 0)
46  {
47  /* Don't give an error if this wasn't a symlink */
48  if ((my_errno=errno) == EINVAL)
49  {
50  result= 1;
51  strmov(to,filename);
52  }
53  else
54  {
55  if (MyFlags & MY_WME)
56  {
57  char errbuf[MYSYS_STRERROR_SIZE];
58  my_error(EE_CANT_READLINK, MYF(0), filename,
59  errno, my_strerror(errbuf, sizeof(errbuf), errno));
60  }
61  result= -1;
62  }
63  }
64  else
65  to[length]=0;
66  DBUG_PRINT("exit" ,("result: %d", result));
67  DBUG_RETURN(result);
68 #endif /* HAVE_READLINK */
69 }
70 
71 
72 /* Create a symbolic link */
73 
74 int my_symlink(const char *content, const char *linkname, myf MyFlags)
75 {
76 #ifndef HAVE_READLINK
77  return 0;
78 #else
79  int result;
80  DBUG_ENTER("my_symlink");
81  DBUG_PRINT("enter",("content: %s linkname: %s", content, linkname));
82 
83  result= 0;
84  if (symlink(content, linkname))
85  {
86  result= -1;
87  my_errno=errno;
88  if (MyFlags & MY_WME)
89  {
90  char errbuf[MYSYS_STRERROR_SIZE];
91  my_error(EE_CANT_SYMLINK, MYF(0), linkname, content,
92  errno, my_strerror(errbuf, sizeof(errbuf), errno));
93  }
94  }
95  else if ((MyFlags & MY_SYNC_DIR) && my_sync_dir_by_file(linkname, MyFlags))
96  result= -1;
97  DBUG_RETURN(result);
98 #endif /* HAVE_READLINK */
99 }
100 
101 #if defined(SCO)
102 #define BUFF_LEN 4097
103 #elif defined(MAXPATHLEN)
104 #define BUFF_LEN MAXPATHLEN
105 #else
106 #define BUFF_LEN FN_LEN
107 #endif
108 
109 
110 int my_is_symlink(const char *filename __attribute__((unused)))
111 {
112 #if defined (HAVE_LSTAT) && defined (S_ISLNK)
113  struct stat stat_buff;
114  return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
115 #elif defined (_WIN32)
116  DWORD dwAttr = GetFileAttributes(filename);
117  return (dwAttr != INVALID_FILE_ATTRIBUTES) &&
118  (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT);
119 #else /* No symlinks */
120  return 0;
121 #endif
122 }
123 
124 /*
125  Resolve all symbolic links in path
126  'to' may be equal to 'filename'
127 */
128 
129 int my_realpath(char *to, const char *filename, myf MyFlags)
130 {
131 #if defined(HAVE_REALPATH) && !defined(HAVE_BROKEN_REALPATH)
132  int result=0;
133  char buff[BUFF_LEN];
134  char *ptr;
135  DBUG_ENTER("my_realpath");
136 
137  DBUG_PRINT("info",("executing realpath"));
138  if ((ptr=realpath(filename,buff)))
139  strmake(to,ptr,FN_REFLEN-1);
140  else
141  {
142  /*
143  Realpath didn't work; Use my_load_path() which is a poor substitute
144  original name but will at least be able to resolve paths that starts
145  with '.'.
146  */
147  DBUG_PRINT("error",("realpath failed with errno: %d", errno));
148  my_errno=errno;
149  if (MyFlags & MY_WME)
150  {
151  char errbuf[MYSYS_STRERROR_SIZE];
152  my_error(EE_REALPATH, MYF(0), filename,
153  my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
154  }
155  my_load_path(to, filename, NullS);
156  result= -1;
157  }
158  DBUG_RETURN(result);
159 #elif defined(_WIN32)
160  int ret= GetFullPathName(filename,FN_REFLEN, to, NULL);
161  if (ret == 0 || ret > FN_REFLEN)
162  {
163  my_errno= (ret > FN_REFLEN) ? ENAMETOOLONG : GetLastError();
164  if (MyFlags & MY_WME)
165  {
166  char errbuf[MYSYS_STRERROR_SIZE];
167  my_error(EE_REALPATH, MYF(0), filename,
168  my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
169  }
170  /*
171  GetFullPathName didn't work : use my_load_path() which is a poor
172  substitute original name but will at least be able to resolve
173  paths that starts with '.'.
174  */
175  my_load_path(to, filename, NullS);
176  return -1;
177  }
178 #else
179  my_load_path(to, filename, NullS);
180 #endif
181  return 0;
182 }