Drizzled Public API Documentation

mf_pack.cc
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include <config.h>
17 
18 #include <drizzled/internal/my_sys.h>
19 
20 #include <pwd.h>
21 
22 #include <drizzled/internal/m_string.h>
23 #include "my_static.h"
24 
25 namespace drizzled
26 {
27 namespace internal
28 {
29 
30 static char * expand_tilde(char * *path);
31 static size_t system_filename(char * to, const char *from);
32 
33 /*
34  remove unwanted chars from dirname
35 
36  SYNOPSIS
37  cleanup_dirname()
38  to Store result here
39  from Dirname to fix. May be same as to
40 
41  IMPLEMENTATION
42  "/../" removes prev dir
43  "/~/" removes all before ~
44  //" is same as "/", except on Win32 at start of a file
45  "/./" is removed
46  Unpacks home_dir if "~/.." used
47  Unpacks current dir if if "./.." used
48 
49  RETURN
50  # length of new name
51 */
52 
53 static size_t cleanup_dirname(char *to, const char *from)
54 {
55  size_t length;
56  char * pos;
57  const char * from_ptr;
58  char * start;
59  char parent[5], /* for "FN_PARENTDIR" */
60  buff[FN_REFLEN+1],*end_parentdir;
61 
62  start=buff;
63  from_ptr= from;
64 #ifdef FN_DEVCHAR
65  if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
66  { /* Skip device part */
67  length=(size_t) (pos-from_ptr)+1;
68  start= strncpy(buff,from_ptr,length);
69  start+= strlen(from_ptr);
70  from_ptr+=length;
71  }
72 #endif
73 
74  parent[0]=FN_LIBCHAR;
75  length= (size_t)((strcpy(parent+1,FN_PARENTDIR)+strlen(FN_PARENTDIR))-parent);
76  for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
77  {
78 #ifdef BACKSLASH_MBTAIL
79  uint32_t l;
80  if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2)))
81  {
82  for (l-- ; l ; *++pos= *from_ptr++, l--);
83  start= pos + 1; /* Don't look inside multi-byte char */
84  continue;
85  }
86 #endif
87  if (*pos == '/')
88  *pos = FN_LIBCHAR;
89  if (*pos == FN_LIBCHAR)
90  {
91  if ((size_t) (pos-start) > length &&
92  memcmp(pos-length,parent,length) == 0)
93  { /* If .../../; skip prev */
94  pos-=length;
95  if (pos != start)
96  { /* not /../ */
97  pos--;
98  if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR))
99  {
100  if (!home_dir)
101  {
102  pos+=length+1; /* Don't unpack ~/.. */
103  continue;
104  }
105  pos= strcpy(buff,home_dir)+strlen(home_dir)-1; /* Unpacks ~/.. */
106  if (*pos == FN_LIBCHAR)
107  pos--; /* home ended with '/' */
108  }
109  if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
110  {
111  if (getcwd(curr_dir,FN_REFLEN))
112  {
113  pos+=length+1; /* Don't unpack ./.. */
114  continue;
115  }
116  pos= strcpy(buff,curr_dir)+strlen(curr_dir)-1; /* Unpacks ./.. */
117  if (*pos == FN_LIBCHAR)
118  pos--; /* home ended with '/' */
119  }
120  end_parentdir=pos;
121  while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */
122  pos--;
123  if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0)
124  { /* Don't remove ~user/ */
125  pos= strcpy(end_parentdir+1,parent)+strlen(parent);
126  *pos=FN_LIBCHAR;
127  continue;
128  }
129  }
130  }
131  else if ((size_t) (pos-start) == length-1 &&
132  !memcmp(start,parent+1,length-1))
133  start=pos; /* Starts with "../" */
134  else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
135  {
136 #ifdef FN_NETWORK_DRIVES
137  if (pos-start != 1)
138 #endif
139  pos--; /* Remove dupplicate '/' */
140  }
141  else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
142  pos-=2; /* Skip /./ */
143  else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
144  { /* Found ..../~/ */
145  buff[0]=FN_HOMELIB;
146  buff[1]=FN_LIBCHAR;
147  start=buff; pos=buff+1;
148  }
149  }
150  }
151  (void) strcpy(to,buff);
152  return((size_t) (pos-buff));
153 } /* cleanup_dirname */
154 
155 
156 /*
157  On system where you don't have symbolic links, the following
158  code will allow you to create a file:
159  directory-name.sym that should contain the real path
160  to the directory. This will be used if the directory name
161  doesn't exists
162 */
163 
164 
165 bool my_use_symdir=0; /* Set this if you want to use symdirs */
166 
167 
168 /*
169  Fixes a directroy name so that can be used by open()
170 
171  SYNOPSIS
172  unpack_dirname()
173  to result-buffer, FN_REFLEN characters. may be == from
174  from 'Packed' directory name (may contain ~)
175 
176  IMPLEMENTATION
177  Make that last char of to is '/' if from not empty and
178  from doesn't end in FN_DEVCHAR
179  Uses cleanup_dirname and changes ~/.. to home_dir/..
180 
181  Changes a UNIX filename to system filename (replaces / with \ on windows)
182 
183  RETURN
184  Length of new directory name (= length of to)
185 */
186 
187 size_t unpack_dirname(char * to, const char *from)
188 {
189  size_t length, h_length;
190  char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
191 
192  (void) intern_filename(buff,from); /* Change to intern name */
193  length= strlen(buff); /* Fix that '/' is last */
194  if (length &&
195 #ifdef FN_DEVCHAR
196  buff[length-1] != FN_DEVCHAR &&
197 #endif
198  buff[length-1] != FN_LIBCHAR && buff[length-1] != '/')
199  {
200  buff[length]=FN_LIBCHAR;
201  buff[length+1]= '\0';
202  }
203 
204  length=cleanup_dirname(buff,buff);
205  if (buff[0] == FN_HOMELIB)
206  {
207  suffix=buff+1; tilde_expansion=expand_tilde(&suffix);
208  if (tilde_expansion)
209  {
210  length-= (size_t) (suffix-buff)-1;
211  if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN)
212  {
213  if (tilde_expansion[h_length-1] == FN_LIBCHAR)
214  h_length--;
215  if (buff+h_length < suffix)
216  memmove(buff+h_length, suffix, length);
217  else
218  bmove_upp((unsigned char*) buff+h_length+length, (unsigned char*) suffix+length, length);
219  memmove(buff, tilde_expansion, h_length);
220  }
221  }
222  }
223  return(system_filename(to,buff)); /* Fix for open */
224 } /* unpack_dirname */
225 
226 
227  /* Expand tilde to home or user-directory */
228  /* Path is reset to point at FN_LIBCHAR after ~xxx */
229 
230 static char * expand_tilde(char * *path)
231 {
232  if (path[0][0] == FN_LIBCHAR)
233  return home_dir; /* ~/ expanded to home */
234  char *str,save;
235  struct passwd *user_entry;
236 
237  if (!(str=strchr(*path,FN_LIBCHAR)))
238  str= strchr(*path, '\0');
239  save= *str; *str= '\0';
240  user_entry=getpwnam(*path);
241  *str=save;
242  endpwent();
243  if (user_entry)
244  {
245  *path=str;
246  return user_entry->pw_dir;
247  }
248  return NULL;
249 }
250 
251 
252 /*
253  Fix filename so it can be used by open, create
254 
255  SYNOPSIS
256  unpack_filename()
257  to Store result here. Must be at least of size FN_REFLEN.
258  from Filename in unix format (with ~)
259 
260  RETURN
261  # length of to
262 
263  NOTES
264  to may be == from
265  ~ will only be expanded if total length < FN_REFLEN
266 */
267 
268 
269 size_t unpack_filename(char * to, const char *from)
270 {
271  size_t length, n_length, buff_length;
272  char buff[FN_REFLEN];
273 
274  length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
275  n_length=unpack_dirname(buff,buff);
276  if (n_length+strlen(from+length) < FN_REFLEN)
277  {
278  (void) strcpy(buff+n_length,from+length);
279  length= system_filename(to,buff); /* Fix to usably filename */
280  }
281  else
282  length= system_filename(to,from); /* Fix to usably filename */
283  return(length);
284 } /* unpack_filename */
285 
286 
287  /* Convert filename (unix standard) to system standard */
288  /* Used before system command's like open(), create() .. */
289  /* Returns used length of to; total length should be FN_REFLEN */
290 
291 static size_t system_filename(char * to, const char *from)
292 {
293  return strlen(strncpy(to,from,FN_REFLEN-1));
294 } /* system_filename */
295 
296 
297  /* Fix a filename to intern (UNIX format) */
298 
299 char *intern_filename(char *to, const char *from)
300 {
301  size_t length, to_length;
302  char buff[FN_REFLEN];
303  if (from == to)
304  { /* Dirname may destroy from */
305  strcpy(buff,from);
306  from=buff;
307  }
308  length= dirname_part(to, from, &to_length); /* Copy dirname & fix chars */
309  (void) strcpy(to + to_length,from+length);
310  return (to);
311 } /* intern_filename */
312 
313 } /* namespace internal */
314 } /* namespace drizzled */