Drizzled Public API Documentation

mf_format.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 <fcntl.h>
00021 
00022 #ifdef HAVE_SYS_STAT_H
00023 # include <sys/stat.h>
00024 #endif
00025 
00026 #include <algorithm>
00027 
00028 #include <drizzled/internal/m_string.h>
00029 
00030 using namespace std;
00031 
00032 namespace drizzled
00033 {
00034 namespace internal
00035 {
00036 
00037 /*
00038   Formats a filename with possible replace of directory of extension
00039   Function can handle the case where 'to' == 'name'
00040   For a description of the flag values, consult my_sys.h
00041   The arguments should be in unix format.
00042 */
00043 
00044 char * fn_format(char * to, const char *name, const char *dir,
00045         const char *extension, uint32_t flag)
00046 {
00047   char dev[FN_REFLEN], buff[FN_REFLEN], *pos;
00048   const char *startpos = name;
00049   const char *ext;
00050   size_t length;
00051   size_t dev_length;
00052 
00053   /* Copy and skip directory */
00054   name+=(length=dirname_part(dev, startpos, &dev_length));
00055   if (length == 0 || (flag & MY_REPLACE_DIR))
00056   {
00057     /* Use given directory */
00058     convert_dirname(dev,dir,NULL);    /* Fix to this OS */
00059   }
00060   else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(dev))
00061   {
00062     /* Put 'dir' before the given path */
00063     strncpy(buff,dev,sizeof(buff)-1);
00064     pos=convert_dirname(dev,dir,NULL);
00065     strncpy(pos,buff,sizeof(buff)-1- (int) (pos-dev));
00066   }
00067 
00068   if (flag & MY_UNPACK_FILENAME)
00069     (void) unpack_dirname(dev,dev);   /* Replace ~/.. with dir */
00070 
00071   if (!(flag & MY_APPEND_EXT) &&
00072       (pos= (char*) strchr(name,FN_EXTCHAR)) != NULL)
00073   {
00074     if ((flag & MY_REPLACE_EXT) == 0)   /* If we should keep old ext */
00075     {
00076       length=strlength(name);     /* Use old extension */
00077       ext = "";
00078     }
00079     else
00080     {
00081       length= (size_t) (pos-(char*) name);  /* Change extension */
00082       ext= extension;
00083     }
00084   }
00085   else
00086   {
00087     length=strlength(name);     /* No ext, use the now one */
00088     ext=extension;
00089   }
00090 
00091   if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN )
00092   {
00093     /* To long path, return original or NULL */
00094     size_t tmp_length;
00095     if (flag & MY_SAFE_PATH)
00096       return NULL;
00097     tmp_length= min(strlength(startpos), (size_t)(FN_REFLEN-1));
00098     strncpy(to,startpos,tmp_length);
00099     to[tmp_length]= '\0';
00100   }
00101   else
00102   {
00103     if (to == startpos)
00104     {
00105       memmove(buff, name, length); /* Save name for last copy */
00106       name=buff;
00107     }
00108     char *tmp= strcpy(to, dev) + strlen(dev);
00109     pos= strncpy(tmp,name,length) + length;
00110     (void) strcpy(pos,ext);     /* Don't convert extension */
00111   }
00112   /*
00113     If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do
00114     realpath if the file is a symbolic link
00115   */
00116   if (flag & MY_RETURN_REAL_PATH)
00117   {
00118     struct stat stat_buff;
00119     char rp_buff[PATH_MAX];
00120     if ((!flag & MY_RESOLVE_SYMLINKS) || 
00121        (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
00122     {
00123       if (!realpath(to,rp_buff))
00124         my_load_path(rp_buff, to, NULL);
00125       rp_buff[FN_REFLEN-1]= '\0';
00126       strcpy(to,rp_buff);
00127     }
00128   }
00129   else if (flag & MY_RESOLVE_SYMLINKS)
00130   {
00131     strcpy(buff,to);
00132     ssize_t sym_link_size= readlink(buff,to,FN_REFLEN-1);
00133     if (sym_link_size >= 0)
00134       to[sym_link_size]= '\0';
00135   }
00136   return(to);
00137 } /* fn_format */
00138 
00139 
00140 /*
00141   strlength(const string str)
00142   Return length of string with end-space:s not counted.
00143 */
00144 
00145 size_t strlength(const char *str)
00146 {
00147   const char* found= str;
00148   const char* pos= str;
00149 
00150   while (*pos)
00151   {
00152     if (*pos != ' ')
00153     {
00154       while (*++pos && *pos != ' ') {};
00155       if (!*pos)
00156       {
00157   found=pos;      /* String ends here */
00158   break;
00159       }
00160     }
00161     found=pos;
00162     while (*++pos == ' ') {};
00163   }
00164   return((size_t) (found - str));
00165 } /* strlength */
00166 
00167 } /* namespace internal */
00168 } /* namespace drizzled */