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