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