Drizzled Public API Documentation

mf_pack.cc

00001 /* Copyright (C) 2000 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 #include <config.h>
00017 
00018 #include <drizzled/internal/my_sys.h>
00019 
00020 #include <pwd.h>
00021 
00022 #include <drizzled/internal/m_string.h>
00023 #include "my_static.h"
00024 
00025 namespace drizzled
00026 {
00027 namespace internal
00028 {
00029 
00030 static char * expand_tilde(char * *path);
00031 static size_t system_filename(char * to, const char *from);
00032 
00033 /*
00034   remove unwanted chars from dirname
00035 
00036   SYNOPSIS
00037      cleanup_dirname()
00038      to   Store result here
00039      from Dirname to fix.  May be same as to
00040 
00041   IMPLEMENTATION
00042   "/../" removes prev dir
00043   "/~/" removes all before ~
00044   //" is same as "/", except on Win32 at start of a file
00045   "/./" is removed
00046   Unpacks home_dir if "~/.." used
00047   Unpacks current dir if if "./.." used
00048 
00049   RETURN
00050     #  length of new name
00051 */
00052 
00053 static size_t cleanup_dirname(char *to, const char *from)
00054 {
00055   size_t length;
00056   char * pos;
00057   const char * from_ptr;
00058   char * start;
00059   char parent[5],       /* for "FN_PARENTDIR" */
00060        buff[FN_REFLEN+1],*end_parentdir;
00061 
00062   start=buff;
00063   from_ptr= from;
00064 #ifdef FN_DEVCHAR
00065   if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
00066   {           /* Skip device part */
00067     length=(size_t) (pos-from_ptr)+1;
00068     start= strncpy(buff,from_ptr,length);
00069     start+= strlen(from_ptr);
00070     from_ptr+=length;
00071   }
00072 #endif
00073 
00074   parent[0]=FN_LIBCHAR;
00075   length= (size_t)((strcpy(parent+1,FN_PARENTDIR)+strlen(FN_PARENTDIR))-parent);
00076   for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
00077   {
00078 #ifdef BACKSLASH_MBTAIL
00079     uint32_t l;
00080     if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2)))
00081     {
00082       for (l-- ; l ; *++pos= *from_ptr++, l--);
00083       start= pos + 1; /* Don't look inside multi-byte char */
00084       continue;
00085     }
00086 #endif
00087     if (*pos == '/')
00088       *pos = FN_LIBCHAR;
00089     if (*pos == FN_LIBCHAR)
00090     {
00091       if ((size_t) (pos-start) > length &&
00092           memcmp(pos-length,parent,length) == 0)
00093       {           /* If .../../; skip prev */
00094   pos-=length;
00095   if (pos != start)
00096   {          /* not /../ */
00097     pos--;
00098     if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR))
00099     {
00100       if (!home_dir)
00101       {
00102         pos+=length+1;      /* Don't unpack ~/.. */
00103         continue;
00104       }
00105       pos= strcpy(buff,home_dir)+strlen(home_dir)-1;  /* Unpacks ~/.. */
00106       if (*pos == FN_LIBCHAR)
00107         pos--;        /* home ended with '/' */
00108     }
00109     if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
00110     {
00111       if (getcwd(curr_dir,FN_REFLEN))
00112       {
00113         pos+=length+1;      /* Don't unpack ./.. */
00114         continue;
00115       }
00116       pos= strcpy(buff,curr_dir)+strlen(curr_dir)-1;  /* Unpacks ./.. */
00117       if (*pos == FN_LIBCHAR)
00118         pos--;        /* home ended with '/' */
00119     }
00120     end_parentdir=pos;
00121     while (pos >= start && *pos != FN_LIBCHAR)  /* remove prev dir */
00122       pos--;
00123     if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0)
00124     {         /* Don't remove ~user/ */
00125       pos= strcpy(end_parentdir+1,parent)+strlen(parent);
00126       *pos=FN_LIBCHAR;
00127       continue;
00128     }
00129   }
00130       }
00131       else if ((size_t) (pos-start) == length-1 &&
00132          !memcmp(start,parent+1,length-1))
00133   start=pos;        /* Starts with "../" */
00134       else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
00135       {
00136 #ifdef FN_NETWORK_DRIVES
00137   if (pos-start != 1)
00138 #endif
00139     pos--;      /* Remove dupplicate '/' */
00140       }
00141       else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
00142   pos-=2;         /* Skip /./ */
00143       else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
00144       {         /* Found ..../~/  */
00145   buff[0]=FN_HOMELIB;
00146   buff[1]=FN_LIBCHAR;
00147   start=buff; pos=buff+1;
00148       }
00149     }
00150   }
00151   (void) strcpy(to,buff);
00152   return((size_t) (pos-buff));
00153 } /* cleanup_dirname */
00154 
00155 
00156 /*
00157   On system where you don't have symbolic links, the following
00158   code will allow you to create a file:
00159   directory-name.sym that should contain the real path
00160   to the directory.  This will be used if the directory name
00161   doesn't exists
00162 */
00163 
00164 
00165 bool my_use_symdir=0; /* Set this if you want to use symdirs */
00166 
00167 
00168 /*
00169   Fixes a directroy name so that can be used by open()
00170 
00171   SYNOPSIS
00172     unpack_dirname()
00173     to      result-buffer, FN_REFLEN characters. may be == from
00174     from    'Packed' directory name (may contain ~)
00175 
00176  IMPLEMENTATION
00177   Make that last char of to is '/' if from not empty and
00178   from doesn't end in FN_DEVCHAR
00179   Uses cleanup_dirname and changes ~/.. to home_dir/..
00180 
00181   Changes a UNIX filename to system filename (replaces / with \ on windows)
00182 
00183   RETURN
00184    Length of new directory name (= length of to)
00185 */
00186 
00187 size_t unpack_dirname(char * to, const char *from)
00188 {
00189   size_t length, h_length;
00190   char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;
00191 
00192   (void) intern_filename(buff,from);      /* Change to intern name */
00193   length= strlen(buff);                     /* Fix that '/' is last */
00194   if (length &&
00195 #ifdef FN_DEVCHAR
00196       buff[length-1] != FN_DEVCHAR &&
00197 #endif
00198       buff[length-1] != FN_LIBCHAR && buff[length-1] != '/')
00199   {
00200     buff[length]=FN_LIBCHAR;
00201     buff[length+1]= '\0';
00202   }
00203 
00204   length=cleanup_dirname(buff,buff);
00205   if (buff[0] == FN_HOMELIB)
00206   {
00207     suffix=buff+1; tilde_expansion=expand_tilde(&suffix);
00208     if (tilde_expansion)
00209     {
00210       length-= (size_t) (suffix-buff)-1;
00211       if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN)
00212       {
00213   if (tilde_expansion[h_length-1] == FN_LIBCHAR)
00214     h_length--;
00215   if (buff+h_length < suffix)
00216           memmove(buff+h_length, suffix, length);
00217   else
00218     bmove_upp((unsigned char*) buff+h_length+length, (unsigned char*) suffix+length, length);
00219         memmove(buff, tilde_expansion, h_length);
00220       }
00221     }
00222   }
00223   return(system_filename(to,buff)); /* Fix for open */
00224 } /* unpack_dirname */
00225 
00226 
00227   /* Expand tilde to home or user-directory */
00228   /* Path is reset to point at FN_LIBCHAR after ~xxx */
00229 
00230 static char * expand_tilde(char * *path)
00231 {
00232   if (path[0][0] == FN_LIBCHAR)
00233     return home_dir;      /* ~/ expanded to home */
00234   char *str,save;
00235   struct passwd *user_entry;
00236 
00237   if (!(str=strchr(*path,FN_LIBCHAR)))
00238     str= strchr(*path, '\0');
00239   save= *str; *str= '\0';
00240   user_entry=getpwnam(*path);
00241   *str=save;
00242   endpwent();
00243   if (user_entry)
00244   {
00245     *path=str;
00246     return user_entry->pw_dir;
00247   }
00248   return NULL;
00249 }
00250 
00251 
00252 /*
00253   Fix filename so it can be used by open, create
00254 
00255   SYNOPSIS
00256     unpack_filename()
00257     to    Store result here. Must be at least of size FN_REFLEN.
00258     from  Filename in unix format (with ~)
00259 
00260   RETURN
00261     # length of to
00262 
00263   NOTES
00264     to may be == from
00265     ~ will only be expanded if total length < FN_REFLEN
00266 */
00267 
00268 
00269 size_t unpack_filename(char * to, const char *from)
00270 {
00271   size_t length, n_length, buff_length;
00272   char buff[FN_REFLEN];
00273 
00274   length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
00275   n_length=unpack_dirname(buff,buff);
00276   if (n_length+strlen(from+length) < FN_REFLEN)
00277   {
00278     (void) strcpy(buff+n_length,from+length);
00279     length= system_filename(to,buff);   /* Fix to usably filename */
00280   }
00281   else
00282     length= system_filename(to,from);   /* Fix to usably filename */
00283   return(length);
00284 } /* unpack_filename */
00285 
00286 
00287   /* Convert filename (unix standard) to system standard */
00288   /* Used before system command's like open(), create() .. */
00289   /* Returns used length of to; total length should be FN_REFLEN */
00290 
00291 static size_t system_filename(char * to, const char *from)
00292 {
00293   return strlen(strncpy(to,from,FN_REFLEN-1));
00294 } /* system_filename */
00295 
00296 
00297   /* Fix a filename to intern (UNIX format) */
00298 
00299 char *intern_filename(char *to, const char *from)
00300 {
00301   size_t length, to_length;
00302   char buff[FN_REFLEN];
00303   if (from == to)
00304   {           /* Dirname may destroy from */
00305     strcpy(buff,from);
00306     from=buff;
00307   }
00308   length= dirname_part(to, from, &to_length); /* Copy dirname & fix chars */
00309   (void) strcpy(to + to_length,from+length);
00310   return (to);
00311 } /* intern_filename */
00312 
00313 } /* namespace internal */
00314 } /* namespace drizzled */