~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
#include "mysys_priv.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
17
#include <mystrings/m_string.h>
53.2.7 by Monty Taylor
Changes so that removal of duplicate curr_dir from my_sys.h work.
18
#include "my_static.h"
1 by brian
clean slate
19
#ifdef HAVE_PWD_H
20
#include <pwd.h>
21
#endif
22
23
static char * expand_tilde(char * *path);
24
25
26
/*
27
  remove unwanted chars from dirname
28
29
  SYNOPSIS
30
     cleanup_dirname()
31
     to		Store result here
32
     from	Dirname to fix.  May be same as to
33
34
  IMPLEMENTATION
35
  "/../" removes prev dir
36
  "/~/" removes all before ~
37
  //" is same as "/", except on Win32 at start of a file
38
  "/./" is removed
39
  Unpacks home_dir if "~/.." used
40
  Unpacks current dir if if "./.." used
41
42
  RETURN
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
43
    #  length of new name
1 by brian
clean slate
44
*/
45
46
size_t cleanup_dirname(register char *to, const char *from)
47
{
48
  register size_t length;
49
  register char * pos;
266.7.15 by Andy Lester
Added a proper const qualifer.
50
  register const char * from_ptr;
1 by brian
clean slate
51
  register char * start;
52
  char parent[5],				/* for "FN_PARENTDIR" */
53
       buff[FN_REFLEN+1],*end_parentdir;
54
#ifdef BACKSLASH_MBTAIL
55
  CHARSET_INFO *fs= fs_character_set();
56
#endif
57
58
  start=buff;
266.7.15 by Andy Lester
Added a proper const qualifer.
59
  from_ptr= from;
1 by brian
clean slate
60
#ifdef FN_DEVCHAR
61
  if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
62
  {						/* Skip device part */
63
    length=(size_t) (pos-from_ptr)+1;
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
64
    start= strncpy(buff,from_ptr,length);
65
    start+= strlen(from_ptr);
66
    from_ptr+=length;
1 by brian
clean slate
67
  }
68
#endif
69
70
  parent[0]=FN_LIBCHAR;
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
71
  length= (size_t)((strcpy(parent+1,FN_PARENTDIR)+strlen(FN_PARENTDIR))-parent);
1 by brian
clean slate
72
  for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
73
  {
74
#ifdef BACKSLASH_MBTAIL
482 by Brian Aker
Remove uint.
75
    uint32_t l;
1 by brian
clean slate
76
    if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2)))
77
    {
78
      for (l-- ; l ; *++pos= *from_ptr++, l--);
79
      start= pos + 1; /* Don't look inside multi-byte char */
80
      continue;
81
    }
82
#endif
83
    if (*pos == '/')
84
      *pos = FN_LIBCHAR;
85
    if (*pos == FN_LIBCHAR)
86
    {
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
87
      if ((size_t) (pos-start) > length &&
88
          memcmp(pos-length,parent,length) == 0)
1 by brian
clean slate
89
      {						/* If .../../; skip prev */
90
	pos-=length;
91
	if (pos != start)
92
	{					 /* not /../ */
93
	  pos--;
94
	  if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR))
95
	  {
96
	    if (!home_dir)
97
	    {
98
	      pos+=length+1;			/* Don't unpack ~/.. */
99
	      continue;
100
	    }
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
101
	    pos= strcpy(buff,home_dir)+strlen(home_dir)-1;	/* Unpacks ~/.. */
1 by brian
clean slate
102
	    if (*pos == FN_LIBCHAR)
103
	      pos--;				/* home ended with '/' */
104
	  }
105
	  if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
106
	  {
575.4.6 by Monty Taylor
Removed my_getwd.
107
	    if (getcwd(curr_dir,FN_REFLEN))
1 by brian
clean slate
108
	    {
109
	      pos+=length+1;			/* Don't unpack ./.. */
110
	      continue;
111
	    }
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
112
	    pos= strcpy(buff,curr_dir)+strlen(curr_dir)-1;	/* Unpacks ./.. */
1 by brian
clean slate
113
	    if (*pos == FN_LIBCHAR)
114
	      pos--;				/* home ended with '/' */
115
	  }
116
	  end_parentdir=pos;
117
	  while (pos >= start && *pos != FN_LIBCHAR)	/* remove prev dir */
118
	    pos--;
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
119
	  if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0)
1 by brian
clean slate
120
	  {					/* Don't remove ~user/ */
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
121
	    pos= strcpy(end_parentdir+1,parent)+strlen(parent);
1 by brian
clean slate
122
	    *pos=FN_LIBCHAR;
123
	    continue;
124
	  }
125
	}
126
      }
127
      else if ((size_t) (pos-start) == length-1 &&
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
128
	       !memcmp(start,parent+1,length-1))
1 by brian
clean slate
129
	start=pos;				/* Starts with "../" */
130
      else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
131
      {
132
#ifdef FN_NETWORK_DRIVES
133
	if (pos-start != 1)
134
#endif
135
	  pos--;			/* Remove dupplicate '/' */
136
      }
137
      else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
138
	pos-=2;					/* Skip /./ */
139
      else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
140
      {					/* Found ..../~/  */
141
	buff[0]=FN_HOMELIB;
142
	buff[1]=FN_LIBCHAR;
143
	start=buff; pos=buff+1;
144
      }
145
    }
146
  }
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
147
  (void) strcpy(to,buff);
51.3.21 by Jay Pipes
Phase 8 - Remove DBUG from mysys
148
  return((size_t) (pos-buff));
1 by brian
clean slate
149
} /* cleanup_dirname */
150
151
152
/*
153
  On system where you don't have symbolic links, the following
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
154
  code will allow you to create a file:
1 by brian
clean slate
155
  directory-name.sym that should contain the real path
156
  to the directory.  This will be used if the directory name
157
  doesn't exists
158
*/
159
160
146 by Brian Aker
my_bool cleanup.
161
bool my_use_symdir=0;	/* Set this if you want to use symdirs */
1 by brian
clean slate
162
163
#ifdef USE_SYMDIR
164
void symdirget(char *dir)
165
{
166
  char buff[FN_REFLEN];
376 by Brian Aker
strend remove
167
  char *pos= strchr(dir, '\0');
1 by brian
clean slate
168
  if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK))
169
  {
170
    File file;
171
    size_t length;
172
    char temp= *(--pos);            /* May be "/" or "\" */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
173
    strcpy(pos,".sym");
1 by brian
clean slate
174
    file= my_open(dir, O_RDONLY, MYF(0));
175
    *pos++=temp; *pos=0;	  /* Restore old filename */
176
    if (file >= 0)
177
    {
178
      if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0)
179
      {
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
180
        for (pos= buff + length ;
181
             pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
182
             pos --);
183
184
        /* Ensure that the symlink ends with the directory symbol */
185
        if (pos == buff || pos[-1] != FN_LIBCHAR)
186
          *pos++=FN_LIBCHAR;
187
188
        strncpy(dir,buff, FN_REFLEN-1);
1 by brian
clean slate
189
      }
190
      my_close(file, MYF(0));
191
    }
192
  }
193
}
194
#endif /* USE_SYMDIR */
195
196
197
/*
198
  Fixes a directroy name so that can be used by open()
199
200
  SYNOPSIS
201
    unpack_dirname()
202
    to			result-buffer, FN_REFLEN characters. may be == from
203
    from		'Packed' directory name (may contain ~)
204
205
 IMPLEMENTATION
206
  Make that last char of to is '/' if from not empty and
207
  from doesn't end in FN_DEVCHAR
208
  Uses cleanup_dirname and changes ~/.. to home_dir/..
209
210
  Changes a UNIX filename to system filename (replaces / with \ on windows)
211
212
  RETURN
213
   Length of new directory name (= length of to)
214
*/
215
216
size_t unpack_dirname(char * to, const char *from)
217
{
218
  size_t length, h_length;
219
  char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
220
221
  (void) intern_filename(buff,from);	    /* Change to intern name */
222
  length= strlen(buff);                     /* Fix that '/' is last */
223
  if (length &&
224
#ifdef FN_DEVCHAR
225
      buff[length-1] != FN_DEVCHAR &&
226
#endif
227
      buff[length-1] != FN_LIBCHAR && buff[length-1] != '/')
228
  {
229
    buff[length]=FN_LIBCHAR;
230
    buff[length+1]= '\0';
231
  }
232
233
  length=cleanup_dirname(buff,buff);
234
  if (buff[0] == FN_HOMELIB)
235
  {
236
    suffix=buff+1; tilde_expansion=expand_tilde(&suffix);
237
    if (tilde_expansion)
238
    {
239
      length-= (size_t) (suffix-buff)-1;
240
      if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN)
241
      {
242
	if (tilde_expansion[h_length-1] == FN_LIBCHAR)
243
	  h_length--;
244
	if (buff+h_length < suffix)
629.3.6 by Kristian Nielsen
A couple more fixes of previous bmove()->memcpy(), changed to
245
          memmove(buff+h_length, suffix, length);
1 by brian
clean slate
246
	else
481 by Brian Aker
Remove all of uchar.
247
	  bmove_upp((unsigned char*) buff+h_length+length, (unsigned char*) suffix+length, length);
629.3.6 by Kristian Nielsen
A couple more fixes of previous bmove()->memcpy(), changed to
248
        memmove(buff, tilde_expansion, h_length);
1 by brian
clean slate
249
      }
250
    }
251
  }
252
#ifdef USE_SYMDIR
253
  if (my_use_symdir)
254
    symdirget(buff);
255
#endif
51.3.21 by Jay Pipes
Phase 8 - Remove DBUG from mysys
256
  return(system_filename(to,buff));	/* Fix for open */
1 by brian
clean slate
257
} /* unpack_dirname */
258
259
260
	/* Expand tilde to home or user-directory */
261
	/* Path is reset to point at FN_LIBCHAR after ~xxx */
262
263
static char * expand_tilde(char * *path)
264
{
265
  if (path[0][0] == FN_LIBCHAR)
266
    return home_dir;			/* ~/ expanded to home */
267
#ifdef HAVE_GETPWNAM
268
  {
269
    char *str,save;
270
    struct passwd *user_entry;
271
272
    if (!(str=strchr(*path,FN_LIBCHAR)))
376 by Brian Aker
strend remove
273
      str= strchr(*path, '\0');
1 by brian
clean slate
274
    save= *str; *str= '\0';
275
    user_entry=getpwnam(*path);
276
    *str=save;
277
    endpwent();
278
    if (user_entry)
279
    {
280
      *path=str;
281
      return user_entry->pw_dir;
282
    }
283
  }
284
#endif
266.6.8 by Andy Lester
use NULL, not 0
285
  return NULL;
1 by brian
clean slate
286
}
287
288
289
/*
290
  Fix filename so it can be used by open, create
291
292
  SYNOPSIS
293
    unpack_filename()
294
    to		Store result here. Must be at least of size FN_REFLEN.
295
    from	Filename in unix format (with ~)
296
297
  RETURN
298
    # length of to
299
300
  NOTES
301
    to may be == from
302
    ~ will only be expanded if total length < FN_REFLEN
303
*/
304
305
306
size_t unpack_filename(char * to, const char *from)
307
{
308
  size_t length, n_length, buff_length;
309
  char buff[FN_REFLEN];
310
311
  length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
312
  n_length=unpack_dirname(buff,buff);
313
  if (n_length+strlen(from+length) < FN_REFLEN)
314
  {
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
315
    (void) strcpy(buff+n_length,from+length);
1 by brian
clean slate
316
    length= system_filename(to,buff);		/* Fix to usably filename */
317
  }
318
  else
319
    length= system_filename(to,from);		/* Fix to usably filename */
51.3.21 by Jay Pipes
Phase 8 - Remove DBUG from mysys
320
  return(length);
1 by brian
clean slate
321
} /* unpack_filename */
322
323
324
	/* Convert filename (unix standard) to system standard */
325
	/* Used before system command's like open(), create() .. */
326
	/* Returns used length of to; total length should be FN_REFLEN */
327
328
size_t system_filename(char * to, const char *from)
329
{
330
#ifndef FN_C_BEFORE_DIR
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
331
  return strlen(strncpy(to,from,FN_REFLEN-1));
1 by brian
clean slate
332
#else	/* VMS */
333
334
	/* change 'dev:lib/xxx' to 'dev:[lib]xxx' */
335
	/* change 'dev:xxx' to 'dev:xxx' */
336
	/* change './xxx' to 'xxx' */
337
	/* change './lib/' or lib/ to '[.lib]' */
338
	/* change '/x/y/z to '[x.y]x' */
339
	/* change 'dev:/x' to 'dev:[000000]x' */
340
341
  int libchar_found;
342
  size_t length;
343
  char * to_pos,from_pos,pos;
344
  char buff[FN_REFLEN];
345
346
  libchar_found=0;
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
347
  (void) strcpy(buff,from);			 /* If to == from */
1 by brian
clean slate
348
  from_pos= buff;
349
  if ((pos=strrchr(from_pos,FN_DEVCHAR)))	/* Skip device part */
350
  {
351
    pos++;
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
352
    to_pos= strncpy(to,from_pos,(size_t) (pos-from_pos));
353
    to_pos+= strlen(to);
1 by brian
clean slate
354
    from_pos=pos;
355
  }
356
  else
357
    to_pos=to;
358
359
  if (from_pos[0] == FN_CURLIB && from_pos[1] == FN_LIBCHAR)
360
    from_pos+=2;				/* Skip './' */
361
  if (strchr(from_pos,FN_LIBCHAR))
362
  {
363
    *(to_pos++) = FN_C_BEFORE_DIR;
77.1.91 by Monty Taylor
Removed strinstr. It was only used twice in once place in mf_pack... and there
364
    if (strstr(from_pos,FN_ROOTDIR) == from_pos)
1 by brian
clean slate
365
    {
366
      from_pos+=strlen(FN_ROOTDIR);		/* Actually +1 but... */
367
      if (! strchr(from_pos,FN_LIBCHAR))
368
      {						/* No dir, use [000000] */
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
369
	to_pos= strcpy(to_pos,FN_C_ROOT_DIR)+strlen(FN_C_ROOT_DIR);
1 by brian
clean slate
370
	libchar_found++;
371
      }
372
    }
373
    else
374
      *(to_pos++)=FN_C_DIR_SEP;			/* '.' gives current dir */
375
376
    while ((pos=strchr(from_pos,FN_LIBCHAR)))
377
    {
378
      if (libchar_found++)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
379
        *(to_pos++)=FN_C_DIR_SEP;		/* Add '.' between dirs */
77.1.91 by Monty Taylor
Removed strinstr. It was only used twice in once place in mf_pack... and there
380
      if (strstr(from_pos,FN_PARENTDIR) == from_pos &&
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
381
          from_pos+strlen(FN_PARENTDIR) == pos) {
382
        to_pos= strcpy(to_pos,FN_C_PARENT_DIR);	/* Found '../' */
383
        to_pos+= strlen(FN_C_PARENT_DIR);
384
      }
1 by brian
clean slate
385
      else
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
386
      {
387
        to_pos= strncpy(to_pos,from_pos,(size_t) (pos-from_pos));
388
        to_pos+= strlen(to_pos);
389
      }
1 by brian
clean slate
390
      from_pos=pos+1;
391
    }
392
    *(to_pos++)=FN_C_AFTER_DIR;
393
  }
660.1.6 by Eric Herman
trailing whitespace fixup
394
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
395
  strcpy(to_pos, from_pos);
396
  length= strlen(to);
51.3.21 by Jay Pipes
Phase 8 - Remove DBUG from mysys
397
  return(length);
1 by brian
clean slate
398
#endif
399
} /* system_filename */
400
401
402
	/* Fix a filename to intern (UNIX format) */
403
404
char *intern_filename(char *to, const char *from)
405
{
406
  size_t length, to_length;
407
  char buff[FN_REFLEN];
408
  if (from == to)
409
  {						/* Dirname may destroy from */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
410
    strcpy(buff,from);
1 by brian
clean slate
411
    from=buff;
412
  }
413
  length= dirname_part(to, from, &to_length);	/* Copy dirname & fix chars */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
414
  (void) strcpy(to + to_length,from+length);
1 by brian
clean slate
415
  return (to);
416
} /* intern_filename */