Drizzled Public API Documentation

mf_format.cc
1 /* Copyright (C) 2000 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include <config.h>
17 
18 #include <drizzled/internal/my_sys.h>
19 
20 #include <fcntl.h>
21 
22 #ifdef HAVE_SYS_STAT_H
23 # include <sys/stat.h>
24 #endif
25 
26 #include <algorithm>
27 
28 #include <drizzled/internal/m_string.h>
29 
30 using namespace std;
31 
32 namespace drizzled
33 {
34 namespace internal
35 {
36 
37 static size_t strlength(const char *str);
38 
39 /*
40  Formats a filename with possible replace of directory of extension
41  Function can handle the case where 'to' == 'name'
42  For a description of the flag values, consult my_sys.h
43  The arguments should be in unix format.
44 */
45 
46 char * fn_format(char * to, const char *name, const char *dir,
47  const char *extension, uint32_t flag)
48 {
49  char dev[FN_REFLEN], buff[FN_REFLEN], *pos;
50  const char *startpos = name;
51  const char *ext;
52  size_t length;
53  size_t dev_length;
54 
55  /* Copy and skip directory */
56  name+=(length=dirname_part(dev, startpos, &dev_length));
57  if (length == 0 || (flag & MY_REPLACE_DIR))
58  {
59  /* Use given directory */
60  convert_dirname(dev,dir,NULL); /* Fix to this OS */
61  }
62  else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(dev))
63  {
64  /* Put 'dir' before the given path */
65  strncpy(buff,dev,sizeof(buff)-1);
66  pos=convert_dirname(dev,dir,NULL);
67  strncpy(pos,buff,sizeof(buff)-1- (int) (pos-dev));
68  }
69 
70  if (flag & MY_UNPACK_FILENAME)
71  (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */
72 
73  if (!(flag & MY_APPEND_EXT) &&
74  (pos= (char*) strchr(name,FN_EXTCHAR)) != NULL)
75  {
76  if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */
77  {
78  length=strlength(name); /* Use old extension */
79  ext = "";
80  }
81  else
82  {
83  length= (size_t) (pos-(char*) name); /* Change extension */
84  ext= extension;
85  }
86  }
87  else
88  {
89  length=strlength(name); /* No ext, use the now one */
90  ext=extension;
91  }
92 
93  if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN )
94  {
95  /* To long path, return original or NULL */
96  size_t tmp_length;
97  if (flag & MY_SAFE_PATH)
98  return NULL;
99  tmp_length= min(strlength(startpos), (size_t)(FN_REFLEN-1));
100  strncpy(to,startpos,tmp_length);
101  to[tmp_length]= '\0';
102  }
103  else
104  {
105  if (to == startpos)
106  {
107  memmove(buff, name, length); /* Save name for last copy */
108  name=buff;
109  }
110  char *tmp= strcpy(to, dev) + strlen(dev);
111  pos= strncpy(tmp,name,length) + length;
112  (void) strcpy(pos,ext); /* Don't convert extension */
113  }
114  /*
115  If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do
116  realpath if the file is a symbolic link
117  */
118  if (flag & MY_RETURN_REAL_PATH)
119  {
120  struct stat stat_buff;
121 #ifndef __GNU__
122  char rp_buff[PATH_MAX];
123 #else
124  char *rp_buff = NULL;
125 #endif
126  if ((!flag & MY_RESOLVE_SYMLINKS) ||
127  (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
128  {
129 #ifndef __GNU__
130  if (!realpath(to,rp_buff))
131  my_load_path(rp_buff, to, NULL);
132  rp_buff[FN_REFLEN-1]= '\0';
133  strcpy(to,rp_buff);
134 #else
135  // on hurd PATH_MAX isn't but realpath accept NULL and will malloc
136  rp_buff = realpath(to,NULL);
137  if (!rp_buff) {
138  char buffer[FN_REFLEN];
139  my_load_path(buffer, to, NULL);
140  buffer[FN_REFLEN-1]= '\0';
141  strcpy(to,buffer);
142  } else {
143  if (strlen(rp_buff) >= FN_REFLEN) {
144  rp_buff[FN_REFLEN-1]= '\0';
145  }
146  strcpy(to,rp_buff);
147  free(rp_buff);
148  }
149 #endif
150  }
151  }
152  else if (flag & MY_RESOLVE_SYMLINKS)
153  {
154  strcpy(buff,to);
155  ssize_t sym_link_size= readlink(buff,to,FN_REFLEN-1);
156  if (sym_link_size >= 0)
157  to[sym_link_size]= '\0';
158  }
159  return(to);
160 } /* fn_format */
161 
162 
163 /*
164  strlength(const string str)
165  Return length of string with end-space:s not counted.
166 */
167 
168 static size_t strlength(const char *str)
169 {
170  const char* found= str;
171  const char* pos= str;
172 
173  while (*pos)
174  {
175  if (*pos != ' ')
176  {
177  while (*++pos && *pos != ' ') {};
178  if (!*pos)
179  {
180  found=pos; /* String ends here */
181  break;
182  }
183  }
184  found=pos;
185  while (*++pos == ' ') {};
186  }
187  return((size_t) (found - str));
188 } /* strlength */
189 
190 } /* namespace internal */
191 } /* namespace drizzled */