mf_pack.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. #include "mysys_priv.h"
  18. #include <m_string.h>
  19. #ifdef HAVE_PWD_H
  20. #include <pwd.h>
  21. #endif
  22. #ifdef VMS
  23. #include <rms.h>
  24. #include <iodef.h>
  25. #include <descrip.h>
  26. #endif /* VMS */
  27. static my_string NEAR_F expand_tilde(my_string *path);
  28. /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */
  29. /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */
  30. /* to may be == from */
  31. void pack_dirname(my_string to, const char *from)
  32. {
  33.   int cwd_err;
  34.   uint d_length,length,buff_length;
  35.   my_string start;
  36.   char buff[FN_REFLEN];
  37.   DBUG_ENTER("pack_dirname");
  38.   (void) intern_filename(to,from); /* Change to intern name */
  39. #ifdef FN_DEVCHAR
  40.   if ((start=strrchr(to,FN_DEVCHAR)) != 0) /* Skipp device part */
  41.     start++;
  42.   else
  43. #endif
  44.     start=to;
  45.   LINT_INIT(buff_length);
  46.   if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0))))
  47.   {
  48.     buff_length= (uint) strlen(buff);
  49.     d_length=(uint) (start-to);
  50.     if ((start == to ||
  51.  (buff_length == d_length && !bcmp(buff,start,d_length))) &&
  52. *start != FN_LIBCHAR && *start)
  53.     { /* Put current dir before */
  54.       bchange(to,d_length,buff,buff_length,(uint) strlen(to)+1);
  55.     }
  56.   }
  57.   if ((d_length= cleanup_dirname(to,to)) != 0)
  58.   {
  59.     length=0;
  60.     if (home_dir)
  61.     {
  62.       length= (uint) strlen(home_dir);
  63.       if (home_dir[length-1] == FN_LIBCHAR)
  64. length--; /* Don't test last '/' */
  65.     }
  66.     if (length > 1 && length < d_length)
  67.     { /* test if /xx/yy -> ~/yy */
  68.       if (bcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR)
  69.       {
  70. to[0]=FN_HOMELIB; /* Filename begins with ~ */
  71. (void) strmov_overlapp(to+1,to+length);
  72.       }
  73.     }
  74.     if (! cwd_err)
  75.     { /* Test if cwd is ~/... */
  76.       if (length > 1 && length < buff_length)
  77.       {
  78. if (bcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR)
  79. {
  80.   buff[0]=FN_HOMELIB;
  81.   (void) strmov_overlapp(buff+1,buff+length);
  82. }
  83.       }
  84.       if (is_prefix(to,buff))
  85.       {
  86. length= (uint) strlen(buff);
  87. if (to[length])
  88.   (void) strmov_overlapp(to,to+length); /* Remove everything before */
  89. else
  90. {
  91.   to[0]= FN_CURLIB; /* Put ./ instead of cwd */
  92.   to[1]= FN_LIBCHAR;
  93.   to[2]= '';
  94. }
  95.       }
  96.     }
  97.   }
  98.   DBUG_PRINT("exit",("to: '%s'",to));
  99.   DBUG_VOID_RETURN;
  100. } /* pack_dirname */
  101. /* remove unwanted chars from dirname */
  102. /* if "/../" removes prev dir; "/~/" removes all before ~ */
  103. /* "//" is same as "/", except on Win32 at start of a file  */
  104. /* "/./" is removed */
  105. /* Unpacks home_dir if "~/.." used */
  106. /* Unpacks current dir if if "./.." used */
  107. uint cleanup_dirname(register my_string to, const char *from)
  108. /* to may be == from */
  109. {
  110.   reg5 uint length;
  111.   reg2 my_string pos;
  112.   reg3 my_string from_ptr;
  113.   reg4 my_string start;
  114.   char parent[5], /* for "FN_PARENTDIR" */
  115.        buff[FN_REFLEN+1],*end_parentdir;
  116.   DBUG_ENTER("cleanup_dirname");
  117.   DBUG_PRINT("enter",("from: '%s'",from));
  118.   start=buff;
  119.   from_ptr=(my_string) from;
  120. #ifdef FN_DEVCHAR
  121.   if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
  122.   { /* Skipp device part */
  123.     length=(uint) (pos-from_ptr)+1;
  124.     start=strnmov(buff,from_ptr,length); from_ptr+=length;
  125.   }
  126. #endif
  127.   parent[0]=FN_LIBCHAR;
  128.   length=(uint) (strmov(parent+1,FN_PARENTDIR)-parent);
  129.   for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
  130.   {
  131.     if (*pos == '/')
  132.       *pos = FN_LIBCHAR;
  133.     if (*pos == FN_LIBCHAR)
  134.     {
  135.       if ((uint) (pos-start) > length && bcmp(pos-length,parent,length) == 0)
  136.       { /* If .../../; skipp prev */
  137. pos-=length;
  138. if (pos != start)
  139. {  /* not /../ */
  140.   pos--;
  141.   if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR))
  142.   {
  143.     if (!home_dir)
  144.     {
  145.       pos+=length+1; /* Don't unpack ~/.. */
  146.       continue;
  147.     }
  148.     pos=strmov(buff,home_dir)-1; /* Unpacks ~/.. */
  149.     if (*pos == FN_LIBCHAR)
  150.       pos--; /* home ended with '/' */
  151.   }
  152.   if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
  153.   {
  154.     if (my_getwd(curr_dir,FN_REFLEN,MYF(0)))
  155.     {
  156.       pos+=length+1; /* Don't unpack ./.. */
  157.       continue;
  158.     }
  159.     pos=strmov(buff,curr_dir)-1; /* Unpacks ./.. */
  160.     if (*pos == FN_LIBCHAR)
  161.       pos--; /* home ended with '/' */
  162.   }
  163.   end_parentdir=pos;
  164.   while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */
  165.     pos--;
  166.   if (pos[1] == FN_HOMELIB || bcmp(pos,parent,length) == 0)
  167.   { /* Don't remove ~user/ */
  168.     pos=strmov(end_parentdir+1,parent);
  169.     *pos=FN_LIBCHAR;
  170.     continue;
  171.   }
  172. }
  173.       }
  174.       else if ((uint) (pos-start) == length-1 &&
  175.        !bcmp(start,parent+1,length-1))
  176. start=pos; /* Starts with "../" */
  177.       else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
  178.       {
  179. #ifdef FN_NETWORK_DRIVES
  180. if (pos-start != 1)
  181. #endif
  182.   pos--; /* Remove dupplicate '/' */
  183.       }
  184.       else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
  185. pos-=2; /* Skipp /./ */
  186.       else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
  187.       { /* Found ..../~/  */
  188. buff[0]=FN_HOMELIB;
  189. buff[1]=FN_LIBCHAR;
  190. start=buff; pos=buff+1;
  191.       }
  192.     }
  193.   }
  194.   (void) strmov(to,buff);
  195.   DBUG_PRINT("exit",("to: '%s'",to));
  196.   DBUG_RETURN((uint) (pos-buff));
  197. } /* cleanup_dirname */
  198. /*
  199.   On system where you don't have symbolic links, the following
  200.   code will allow you to create a file: 
  201.   directory-name.lnk that should contain the real path
  202.   to the directory.  This will be used if the directory name
  203.   doesn't exists
  204. */
  205.   
  206. my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
  207. #ifdef USE_SYMDIR
  208. void symdirget(char *dir)
  209. {
  210.   char buff[FN_REFLEN];
  211.   char *pos=strend(dir);
  212.   if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK))
  213.   {
  214.     FILE *fp;
  215.     char temp= *(--pos);            /* May be "/" or "" */
  216.     strmov(pos,".sym");
  217.     fp = my_fopen(dir, O_RDONLY,MYF(0));
  218.     *pos++=temp; *pos=0;   /* Restore old filename */
  219.     if (fp)
  220.     {
  221.       if (fgets(buff, sizeof(buff), fp))
  222.       {
  223. for (pos=strend(buff);
  224.      pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
  225.      pos --);
  226. strmake(dir,buff, (uint) (pos-buff));
  227.       }
  228.       my_fclose(fp,MYF(0));
  229.     }
  230.   }
  231. }
  232. #endif /* USE_SYMDIR */
  233. /* Unpacks dirname to name that can be used by open... */
  234. /* Make that last char of to is '/' if from not empty and
  235.    from doesn't end in FN_DEVCHAR */
  236. /* Uses cleanup_dirname and changes ~/.. to home_dir/.. */
  237. /* Returns length of new directory */
  238. uint unpack_dirname(my_string to, const char *from)
  239.   /* to may be == from */
  240. {
  241.   uint length,h_length;
  242.   char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
  243.   DBUG_ENTER("unpack_dirname");
  244.   (void) intern_filename(buff,from); /* Change to intern name */
  245.   length= (uint) strlen(buff); /* Fix that '/' is last */
  246.   if (length &&
  247. #ifdef FN_DEVCHAR
  248.       buff[length-1] != FN_DEVCHAR &&
  249. #endif
  250.       buff[length-1] != FN_LIBCHAR && buff[length-1] != '/')
  251.   {
  252.     buff[length]=FN_LIBCHAR;
  253.     buff[length+1]= '';
  254.   }
  255.   length=cleanup_dirname(buff,buff);
  256.   if (buff[0] == FN_HOMELIB)
  257.   {
  258.     suffix=buff+1; tilde_expansion=expand_tilde(&suffix);
  259.     if (tilde_expansion)
  260.     {
  261.       length-=(uint) (suffix-buff)-1;
  262.       if (length+(h_length= (uint) strlen(tilde_expansion)) <= FN_REFLEN)
  263.       {
  264. if (tilde_expansion[h_length-1] == FN_LIBCHAR)
  265.   h_length--;
  266. if (buff+h_length < suffix)
  267.   bmove(buff+h_length,suffix,length);
  268. else
  269.   bmove_upp(buff+h_length+length,suffix+length,length);
  270. bmove(buff,tilde_expansion,h_length);
  271.       }
  272.     }
  273.   }
  274. #ifdef USE_SYMDIR
  275.   if (my_use_symdir)
  276.     symdirget(buff);
  277. #endif
  278.   DBUG_RETURN(system_filename(to,buff)); /* Fix for open */
  279. } /* unpack_dirname */
  280. /* Expand tilde to home or user-directory */
  281. /* Path is reset to point at FN_LIBCHAR after ~xxx */
  282. static my_string NEAR_F expand_tilde(my_string *path)
  283. {
  284.   if (path[0][0] == FN_LIBCHAR)
  285.     return home_dir; /* ~/ expanded to home */
  286. #ifdef HAVE_GETPWNAM
  287.   {
  288.     char *str,save;
  289.     struct passwd *user_entry;
  290.     if (!(str=strchr(*path,FN_LIBCHAR)))
  291.       str=strend(*path);
  292.     save= *str; *str= '';
  293.     user_entry=getpwnam(*path);
  294.     *str=save;
  295.     endpwent();
  296.     if (user_entry)
  297.     {
  298.       *path=str;
  299.       return user_entry->pw_dir;
  300.     }
  301.   }
  302. #endif
  303.   return (my_string) 0;
  304. }
  305. /* fix filename so it can be used by open, create .. */
  306. /* to may be == from */
  307. /* Returns to */
  308. my_string unpack_filename(my_string to, const char *from)
  309. {
  310.   uint length,n_length;
  311.   char buff[FN_REFLEN];
  312.   DBUG_ENTER("unpack_filename");
  313.   length=dirname_part(buff,from); /* copy & convert dirname */
  314.   n_length=unpack_dirname(buff,buff);
  315.   if (n_length+strlen(from+length) < FN_REFLEN)
  316.   {
  317.     (void) strmov(buff+n_length,from+length);
  318.     (void) system_filename(to,buff); /* Fix to usably filename */
  319.   }
  320.   else
  321.     (void) system_filename(to,from); /* Fix to usably filename */
  322.   DBUG_RETURN(to);
  323. } /* unpack_filename */
  324. /* Convert filename (unix standard) to system standard */
  325. /* Used before system command's like open(), create() .. */
  326. /* Returns to */
  327. uint system_filename(my_string to, const char *from)
  328. {
  329. #ifndef FN_C_BEFORE_DIR
  330.   return (uint) (strmake(to,from,FN_REFLEN-1)-to);
  331. #else /* VMS */
  332. /* change 'dev:lib/xxx' to 'dev:[lib]xxx' */
  333. /* change 'dev:xxx' to 'dev:xxx' */
  334. /* change './xxx' to 'xxx' */
  335. /* change './lib/' or lib/ to '[.lib]' */
  336. /* change '/x/y/z to '[x.y]x' */
  337. /* change 'dev:/x' to 'dev:[000000]x' */
  338.   int libchar_found,length;
  339.   my_string to_pos,from_pos,pos;
  340.   char buff[FN_REFLEN];
  341.   DBUG_ENTER("system_filename");
  342.   libchar_found=0;
  343.   (void) strmov(buff,from);  /* If to == from */
  344.   from_pos= buff;
  345.   if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */
  346.   {
  347.     pos++;
  348.     to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos));
  349.     from_pos=pos;
  350.   }
  351.   else
  352.     to_pos=to;
  353.   if (from_pos[0] == FN_CURLIB && from_pos[1] == FN_LIBCHAR)
  354.     from_pos+=2; /* Skipp './' */
  355.   if (strchr(from_pos,FN_LIBCHAR))
  356.   {
  357.     *(to_pos++) = FN_C_BEFORE_DIR;
  358.     if (strinstr(from_pos,FN_ROOTDIR) == 1)
  359.     {
  360.       from_pos+=strlen(FN_ROOTDIR); /* Actually +1 but... */
  361.       if (! strchr(from_pos,FN_LIBCHAR))
  362.       { /* No dir, use [000000] */
  363. to_pos=strmov(to_pos,FN_C_ROOT_DIR);
  364. libchar_found++;
  365.       }
  366.     }
  367.     else
  368.       *(to_pos++)=FN_C_DIR_SEP; /* '.' gives current dir */
  369.     while ((pos=strchr(from_pos,FN_LIBCHAR)))
  370.     {
  371.       if (libchar_found++)
  372. *(to_pos++)=FN_C_DIR_SEP; /* Add '.' between dirs */
  373.       if (strinstr(from_pos,FN_PARENTDIR) == 1 &&
  374.   from_pos+strlen(FN_PARENTDIR) == pos)
  375. to_pos=strmov(to_pos,FN_C_PARENT_DIR); /* Found '../' */
  376.       else
  377. to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos));
  378.       from_pos=pos+1;
  379.     }
  380.     *(to_pos++)=FN_C_AFTER_DIR;
  381.   }
  382.   length=(int) (strmov(to_pos,from_pos)-to);
  383.   DBUG_PRINT("exit",("name: '%s'",to));
  384.   DBUG_RETURN((uint) length);
  385. #endif
  386. } /* system_filename */
  387. /* Fix a filename to intern (UNIX format) */
  388. my_string intern_filename(my_string to, const char *from)
  389. {
  390. #ifndef VMS
  391.   {
  392.     uint length;
  393.     char buff[FN_REFLEN];
  394.     if (from == to)
  395.     { /* Dirname may destroy from */
  396.       strmov(buff,from);
  397.       from=buff;
  398.     }
  399.     length=dirname_part(to,from); /* Copy dirname & fix chars */
  400.     (void) strcat(to,from+length);
  401.     return (to);
  402.   }
  403. #else /* VMS */
  404. /* change 'dev:[lib]xxx' to 'dev:lib/xxx' */
  405. /* change 'dev:xxx' to 'dev:xxx' */
  406. /* change 'dev:x/y/[.lib]' to 'dev:x/y/lib/ */
  407. /* change '[.lib]' to './lib/' */
  408. /* change '[x.y]' or '[x.][y]' or '[x][.y]' to '/x/y/' */
  409. /* change '[000000.x] or [x.000000]' to '/x/' */
  410.   int par_length,root_length;
  411.   my_string pos,from_pos,to_pos,end_pos;
  412.   char buff[FN_REFLEN];
  413.   (void) strmov(buff,from);
  414.   convert_dirname(buff); /* change '<>' to '[]' */
  415.   from_pos=buff;
  416.   if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */
  417.   {
  418.     pos++;
  419.     to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos));
  420.     from_pos=pos;
  421.   }
  422.   else
  423.     to_pos=to;
  424.   root_length=strlen(FN_C_ROOT_DIR);
  425.   if ((pos = strchr(from_pos,FN_C_BEFORE_DIR)) &&
  426.       (end_pos = strrchr(pos+1,FN_C_AFTER_DIR)))
  427.   {
  428.     to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos));
  429. /* Copy all between ':' and '[' */
  430.     from_pos=pos+1;
  431.     if (strinstr(from_pos,FN_C_ROOT_DIR) == 1 &&
  432. (from_pos[root_length] == FN_C_DIR_SEP ||
  433.  from_pos[root_length] == FN_C_AFTER_DIR))
  434.     {
  435.       from_pos+=root_length+1;
  436.     }
  437.     else if (*from_pos == FN_C_DIR_SEP)
  438.       *(to_pos++) = FN_CURLIB; /* Set ./ first */
  439.     *(to_pos++) = FN_LIBCHAR;
  440.     par_length=strlen(FN_C_PARENT_DIR);
  441.     pos=to_pos;
  442.     for (; from_pos <= end_pos ; from_pos++)
  443.     {
  444.       switch (*from_pos) {
  445.       case FN_C_DIR_SEP:
  446.       case FN_C_AFTER_DIR:
  447. if (pos != to_pos)
  448. {
  449.   if ((int) (to_pos-pos) == root_length &&
  450.       is_suffix(pos,FN_C_ROOT_DIR))
  451.     to_pos=pos; /* remove root-pos */
  452.   else
  453.   {
  454.     *(to_pos++)=FN_LIBCHAR; /* Find lib */
  455.     pos=to_pos;
  456.   }
  457. }
  458. break;
  459.       case FN_C_BEFORE_DIR:
  460. break;
  461.       case '-': /* *(FN_C_PARENT_DIR): */
  462. if (to_pos[-1] == FN_LIBCHAR &&
  463.     strncmp(from_pos,FN_C_PARENT_DIR,par_length) == 0)
  464. { /* Change '-' to '..' */
  465.   to_pos=strmov(to_pos,FN_PARENTDIR);
  466.   *(to_pos++)=FN_LIBCHAR;
  467.   pos=to_pos;
  468.   from_pos+=par_length-1;
  469.   break;
  470. }
  471. /* Fall through */
  472.       default:
  473. *(to_pos++)= *from_pos;
  474. break;
  475.       }
  476.     }
  477.   }
  478.   (void) strmov(to_pos,from_pos);
  479.   return (to);
  480. #endif /* VMS */
  481. } /* intern_filename */