~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/mf_pack.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:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include "mysys_priv.h"
17
 
#include <mystrings/m_string.h>
18
 
#include "my_static.h"
 
17
#include <m_string.h>
19
18
#ifdef HAVE_PWD_H
20
19
#include <pwd.h>
21
20
#endif
 
21
#ifdef VMS
 
22
#include <rms.h>
 
23
#include <iodef.h>
 
24
#include <descrip.h>
 
25
#endif /* VMS */
22
26
 
23
27
static char * expand_tilde(char * *path);
24
28
 
 
29
        /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */
 
30
        /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */
 
31
        /* to may be == from */
 
32
 
 
33
void pack_dirname(char * to, const char *from)
 
34
{
 
35
  int cwd_err;
 
36
  size_t d_length,length,buff_length= 0;
 
37
  char * start;
 
38
  char buff[FN_REFLEN];
 
39
  DBUG_ENTER("pack_dirname");
 
40
 
 
41
  (void) intern_filename(to,from);              /* Change to intern name */
 
42
 
 
43
#ifdef FN_DEVCHAR
 
44
  if ((start=strrchr(to,FN_DEVCHAR)) != 0)      /* Skip device part */
 
45
    start++;
 
46
  else
 
47
#endif
 
48
    start=to;
 
49
 
 
50
  if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0))))
 
51
  {
 
52
    buff_length= strlen(buff);
 
53
    d_length= (size_t) (start-to);
 
54
    if ((start == to ||
 
55
         (buff_length == d_length && !bcmp(buff,start,d_length))) &&
 
56
        *start != FN_LIBCHAR && *start)
 
57
    {                                           /* Put current dir before */
 
58
      bchange((uchar*) to, d_length, (uchar*) buff, buff_length, strlen(to)+1);
 
59
    }
 
60
  }
 
61
 
 
62
  if ((d_length= cleanup_dirname(to,to)) != 0)
 
63
  {
 
64
    length=0;
 
65
    if (home_dir)
 
66
    {
 
67
      length= strlen(home_dir);
 
68
      if (home_dir[length-1] == FN_LIBCHAR)
 
69
        length--;                               /* Don't test last '/' */
 
70
    }
 
71
    if (length > 1 && length < d_length)
 
72
    {                                           /* test if /xx/yy -> ~/yy */
 
73
      if (bcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR)
 
74
      {
 
75
        to[0]=FN_HOMELIB;                       /* Filename begins with ~ */
 
76
        (void) strmov_overlapp(to+1,to+length);
 
77
      }
 
78
    }
 
79
    if (! cwd_err)
 
80
    {                                           /* Test if cwd is ~/... */
 
81
      if (length > 1 && length < buff_length)
 
82
      {
 
83
        if (bcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR)
 
84
        {
 
85
          buff[0]=FN_HOMELIB;
 
86
          (void) strmov_overlapp(buff+1,buff+length);
 
87
        }
 
88
      }
 
89
      if (is_prefix(to,buff))
 
90
      {
 
91
        length= strlen(buff);
 
92
        if (to[length])
 
93
          (void) strmov_overlapp(to,to+length); /* Remove everything before */
 
94
        else
 
95
        {
 
96
          to[0]= FN_CURLIB;                     /* Put ./ instead of cwd */
 
97
          to[1]= FN_LIBCHAR;
 
98
          to[2]= '\0';
 
99
        }
 
100
      }
 
101
    }
 
102
  }
 
103
  DBUG_PRINT("exit",("to: '%s'",to));
 
104
  DBUG_VOID_RETURN;
 
105
} /* pack_dirname */
 
106
 
25
107
 
26
108
/*
27
109
  remove unwanted chars from dirname
40
122
  Unpacks current dir if if "./.." used
41
123
 
42
124
  RETURN
43
 
    #  length of new name
 
125
    #  length of new name   
44
126
*/
45
127
 
46
128
size_t cleanup_dirname(register char *to, const char *from)
47
129
{
48
130
  register size_t length;
49
131
  register char * pos;
50
 
  register const char * from_ptr;
 
132
  register char * from_ptr;
51
133
  register char * start;
52
134
  char parent[5],                               /* for "FN_PARENTDIR" */
53
135
       buff[FN_REFLEN+1],*end_parentdir;
54
136
#ifdef BACKSLASH_MBTAIL
55
137
  CHARSET_INFO *fs= fs_character_set();
56
138
#endif
 
139
  DBUG_ENTER("cleanup_dirname");
 
140
  DBUG_PRINT("enter",("from: '%s'",from));
57
141
 
58
142
  start=buff;
59
 
  from_ptr= from;
 
143
  from_ptr=(char *) from;
60
144
#ifdef FN_DEVCHAR
61
145
  if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
62
146
  {                                             /* Skip device part */
63
147
    length=(size_t) (pos-from_ptr)+1;
64
 
    start= strncpy(buff,from_ptr,length);
65
 
    start+= strlen(from_ptr);
66
 
    from_ptr+=length;
 
148
    start=strnmov(buff,from_ptr,length); from_ptr+=length;
67
149
  }
68
150
#endif
69
151
 
70
152
  parent[0]=FN_LIBCHAR;
71
 
  length= (size_t)((strcpy(parent+1,FN_PARENTDIR)+strlen(FN_PARENTDIR))-parent);
 
153
  length=(size_t) (strmov(parent+1,FN_PARENTDIR)-parent);
72
154
  for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
73
155
  {
74
156
#ifdef BACKSLASH_MBTAIL
75
 
    uint32_t l;
 
157
    uint l;
76
158
    if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2)))
77
159
    {
78
160
      for (l-- ; l ; *++pos= *from_ptr++, l--);
84
166
      *pos = FN_LIBCHAR;
85
167
    if (*pos == FN_LIBCHAR)
86
168
    {
87
 
      if ((size_t) (pos-start) > length &&
88
 
          memcmp(pos-length,parent,length) == 0)
 
169
      if ((size_t) (pos-start) > length && bcmp(pos-length,parent,length) == 0)
89
170
      {                                         /* If .../../; skip prev */
90
171
        pos-=length;
91
172
        if (pos != start)
98
179
              pos+=length+1;                    /* Don't unpack ~/.. */
99
180
              continue;
100
181
            }
101
 
            pos= strcpy(buff,home_dir)+strlen(home_dir)-1;      /* Unpacks ~/.. */
 
182
            pos=strmov(buff,home_dir)-1;        /* Unpacks ~/.. */
102
183
            if (*pos == FN_LIBCHAR)
103
184
              pos--;                            /* home ended with '/' */
104
185
          }
105
186
          if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
106
187
          {
107
 
            if (getcwd(curr_dir,FN_REFLEN))
 
188
            if (my_getwd(curr_dir,FN_REFLEN,MYF(0)))
108
189
            {
109
190
              pos+=length+1;                    /* Don't unpack ./.. */
110
191
              continue;
111
192
            }
112
 
            pos= strcpy(buff,curr_dir)+strlen(curr_dir)-1;      /* Unpacks ./.. */
 
193
            pos=strmov(buff,curr_dir)-1;        /* Unpacks ./.. */
113
194
            if (*pos == FN_LIBCHAR)
114
195
              pos--;                            /* home ended with '/' */
115
196
          }
116
197
          end_parentdir=pos;
117
198
          while (pos >= start && *pos != FN_LIBCHAR)    /* remove prev dir */
118
199
            pos--;
119
 
          if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0)
 
200
          if (pos[1] == FN_HOMELIB || bcmp(pos,parent,length) == 0)
120
201
          {                                     /* Don't remove ~user/ */
121
 
            pos= strcpy(end_parentdir+1,parent)+strlen(parent);
 
202
            pos=strmov(end_parentdir+1,parent);
122
203
            *pos=FN_LIBCHAR;
123
204
            continue;
124
205
          }
125
206
        }
126
207
      }
127
208
      else if ((size_t) (pos-start) == length-1 &&
128
 
               !memcmp(start,parent+1,length-1))
 
209
               !bcmp(start,parent+1,length-1))
129
210
        start=pos;                              /* Starts with "../" */
130
211
      else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
131
212
      {
144
225
      }
145
226
    }
146
227
  }
147
 
  (void) strcpy(to,buff);
148
 
  return((size_t) (pos-buff));
 
228
  (void) strmov(to,buff);
 
229
  DBUG_PRINT("exit",("to: '%s'",to));
 
230
  DBUG_RETURN((size_t) (pos-buff));
149
231
} /* cleanup_dirname */
150
232
 
151
233
 
152
234
/*
153
235
  On system where you don't have symbolic links, the following
154
 
  code will allow you to create a file:
 
236
  code will allow you to create a file: 
155
237
  directory-name.sym that should contain the real path
156
238
  to the directory.  This will be used if the directory name
157
239
  doesn't exists
158
240
*/
159
241
 
160
242
 
161
 
bool my_use_symdir=0;   /* Set this if you want to use symdirs */
 
243
my_bool my_use_symdir=0;        /* Set this if you want to use symdirs */
162
244
 
163
245
#ifdef USE_SYMDIR
164
246
void symdirget(char *dir)
165
247
{
166
248
  char buff[FN_REFLEN];
167
 
  char *pos= strchr(dir, '\0');
 
249
  char *pos=strend(dir);
168
250
  if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK))
169
251
  {
170
252
    File file;
171
253
    size_t length;
172
254
    char temp= *(--pos);            /* May be "/" or "\" */
173
 
    strcpy(pos,".sym");
 
255
    strmov(pos,".sym");
174
256
    file= my_open(dir, O_RDONLY, MYF(0));
175
257
    *pos++=temp; *pos=0;          /* Restore old filename */
176
258
    if (file >= 0)
177
259
    {
178
260
      if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0)
179
261
      {
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);
 
262
        for (pos= buff + length ;
 
263
             pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
 
264
             pos --);
 
265
 
 
266
        /* Ensure that the symlink ends with the directory symbol */
 
267
        if (pos == buff || pos[-1] != FN_LIBCHAR)
 
268
          *pos++=FN_LIBCHAR;
 
269
 
 
270
        strmake(dir,buff, (size_t) (pos-buff));
189
271
      }
190
272
      my_close(file, MYF(0));
191
273
    }
217
299
{
218
300
  size_t length, h_length;
219
301
  char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
 
302
  DBUG_ENTER("unpack_dirname");
220
303
 
221
304
  (void) intern_filename(buff,from);        /* Change to intern name */
222
305
  length= strlen(buff);                     /* Fix that '/' is last */
242
325
        if (tilde_expansion[h_length-1] == FN_LIBCHAR)
243
326
          h_length--;
244
327
        if (buff+h_length < suffix)
245
 
          memmove(buff+h_length, suffix, length);
 
328
          bmove(buff+h_length,suffix,length);
246
329
        else
247
 
          bmove_upp((unsigned char*) buff+h_length+length, (unsigned char*) suffix+length, length);
248
 
        memmove(buff, tilde_expansion, h_length);
 
330
          bmove_upp((uchar*) buff+h_length+length, (uchar*) suffix+length, length);
 
331
        bmove(buff,tilde_expansion,h_length);
249
332
      }
250
333
    }
251
334
  }
253
336
  if (my_use_symdir)
254
337
    symdirget(buff);
255
338
#endif
256
 
  return(system_filename(to,buff));     /* Fix for open */
 
339
  DBUG_RETURN(system_filename(to,buff));        /* Fix for open */
257
340
} /* unpack_dirname */
258
341
 
259
342
 
270
353
    struct passwd *user_entry;
271
354
 
272
355
    if (!(str=strchr(*path,FN_LIBCHAR)))
273
 
      str= strchr(*path, '\0');
 
356
      str=strend(*path);
274
357
    save= *str; *str= '\0';
275
358
    user_entry=getpwnam(*path);
276
359
    *str=save;
282
365
    }
283
366
  }
284
367
#endif
285
 
  return NULL;
 
368
  return (char *) 0;
286
369
}
287
370
 
288
371
 
307
390
{
308
391
  size_t length, n_length, buff_length;
309
392
  char buff[FN_REFLEN];
 
393
  DBUG_ENTER("unpack_filename");
310
394
 
311
395
  length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
312
396
  n_length=unpack_dirname(buff,buff);
313
397
  if (n_length+strlen(from+length) < FN_REFLEN)
314
398
  {
315
 
    (void) strcpy(buff+n_length,from+length);
 
399
    (void) strmov(buff+n_length,from+length);
316
400
    length= system_filename(to,buff);           /* Fix to usably filename */
317
401
  }
318
402
  else
319
403
    length= system_filename(to,from);           /* Fix to usably filename */
320
 
  return(length);
 
404
  DBUG_RETURN(length);
321
405
} /* unpack_filename */
322
406
 
323
407
 
328
412
size_t system_filename(char * to, const char *from)
329
413
{
330
414
#ifndef FN_C_BEFORE_DIR
331
 
  return strlen(strncpy(to,from,FN_REFLEN-1));
 
415
  return (size_t) (strmake(to,from,FN_REFLEN-1)-to);
332
416
#else   /* VMS */
333
417
 
334
418
        /* change 'dev:lib/xxx' to 'dev:[lib]xxx' */
342
426
  size_t length;
343
427
  char * to_pos,from_pos,pos;
344
428
  char buff[FN_REFLEN];
 
429
  DBUG_ENTER("system_filename");
345
430
 
346
431
  libchar_found=0;
347
 
  (void) strcpy(buff,from);                      /* If to == from */
 
432
  (void) strmov(buff,from);                      /* If to == from */
348
433
  from_pos= buff;
349
434
  if ((pos=strrchr(from_pos,FN_DEVCHAR)))       /* Skip device part */
350
435
  {
351
436
    pos++;
352
 
    to_pos= strncpy(to,from_pos,(size_t) (pos-from_pos));
353
 
    to_pos+= strlen(to);
 
437
    to_pos=strnmov(to,from_pos,(size_t) (pos-from_pos));
354
438
    from_pos=pos;
355
439
  }
356
440
  else
361
445
  if (strchr(from_pos,FN_LIBCHAR))
362
446
  {
363
447
    *(to_pos++) = FN_C_BEFORE_DIR;
364
 
    if (strstr(from_pos,FN_ROOTDIR) == from_pos)
 
448
    if (strinstr(from_pos,FN_ROOTDIR) == 1)
365
449
    {
366
450
      from_pos+=strlen(FN_ROOTDIR);             /* Actually +1 but... */
367
451
      if (! strchr(from_pos,FN_LIBCHAR))
368
452
      {                                         /* No dir, use [000000] */
369
 
        to_pos= strcpy(to_pos,FN_C_ROOT_DIR)+strlen(FN_C_ROOT_DIR);
 
453
        to_pos=strmov(to_pos,FN_C_ROOT_DIR);
370
454
        libchar_found++;
371
455
      }
372
456
    }
376
460
    while ((pos=strchr(from_pos,FN_LIBCHAR)))
377
461
    {
378
462
      if (libchar_found++)
379
 
        *(to_pos++)=FN_C_DIR_SEP;               /* Add '.' between dirs */
380
 
      if (strstr(from_pos,FN_PARENTDIR) == from_pos &&
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
 
      }
 
463
        *(to_pos++)=FN_C_DIR_SEP;               /* Add '.' between dirs */
 
464
      if (strinstr(from_pos,FN_PARENTDIR) == 1 &&
 
465
          from_pos+strlen(FN_PARENTDIR) == pos)
 
466
        to_pos=strmov(to_pos,FN_C_PARENT_DIR);  /* Found '../' */
385
467
      else
386
 
      {
387
 
        to_pos= strncpy(to_pos,from_pos,(size_t) (pos-from_pos));
388
 
        to_pos+= strlen(to_pos);
389
 
      }
 
468
        to_pos=strnmov(to_pos,from_pos,(size_t) (pos-from_pos));
390
469
      from_pos=pos+1;
391
470
    }
392
471
    *(to_pos++)=FN_C_AFTER_DIR;
393
472
  }
394
 
 
395
 
  strcpy(to_pos, from_pos);
396
 
  length= strlen(to);
397
 
  return(length);
 
473
  length= (size_t) (strmov(to_pos,from_pos)-to);
 
474
  DBUG_PRINT("exit",("name: '%s'",to));
 
475
  DBUG_RETURN(length);
398
476
#endif
399
477
} /* system_filename */
400
478
 
407
485
  char buff[FN_REFLEN];
408
486
  if (from == to)
409
487
  {                                             /* Dirname may destroy from */
410
 
    strcpy(buff,from);
 
488
    strmov(buff,from);
411
489
    from=buff;
412
490
  }
413
491
  length= dirname_part(to, from, &to_length);   /* Copy dirname & fix chars */
414
 
  (void) strcpy(to + to_length,from+length);
 
492
  (void) strmov(to + to_length,from+length);
415
493
  return (to);
416
494
} /* intern_filename */