1 /* -*- c-basic-offset: 2 -*- */
2 /*
3   Copyright(C) 2010 Tetsuro IKEDA
4   Copyright(C) 2011-2013 Kentoku SHIBA
5   Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
6 
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 2.1 of the License, or (at your option) any later version.
11 
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   Lesser General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public
18   License along with this library; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA
20 */
21 
22 #include <mrn_mysql.h>
23 
24 #include "mrn_path_mapper.hpp"
25 
26 #include <string.h>
27 
28 namespace mrn {
29   char *PathMapper::default_path_prefix = NULL;
30   char *PathMapper::default_mysql_data_home_path = NULL;
31 
PathMapper(const char * original_mysql_path,const char * path_prefix,const char * mysql_data_home_path)32   PathMapper::PathMapper(const char *original_mysql_path,
33                          const char *path_prefix,
34                          const char *mysql_data_home_path)
35     : original_mysql_path_(original_mysql_path),
36       path_prefix_(path_prefix),
37       mysql_data_home_path_(mysql_data_home_path) {
38     db_path_[0] = '\0';
39     db_name_[0] = '\0';
40     table_name_[0] = '\0';
41     mysql_table_name_[0] = '\0';
42     mysql_path_[0] = '\0';
43   }
44 
45   /**
46    * "./${db}/${table}"                              ==> "${db}.mrn"
47    * "./${db}/"                                      ==> "${db}.mrn"
48    * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0" ==>
49    *   "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0.mrn"
50    */
db_path()51   const char *PathMapper::db_path() {
52     if (db_path_[0] != '\0') {
53       return db_path_;
54     }
55 
56     if (original_mysql_path_[0] == FN_CURLIB &&
57         original_mysql_path_[1] == FN_LIBCHAR) {
58       if (path_prefix_) {
59         strcpy(db_path_, path_prefix_);
60       }
61 
62       int i = 2, j = strlen(db_path_), len;
63       len = strlen(original_mysql_path_);
64       while (original_mysql_path_[i] != FN_LIBCHAR && i < len) {
65         db_path_[j++] = original_mysql_path_[i++];
66       }
67       db_path_[j] = '\0';
68     } else if (mysql_data_home_path_) {
69       int len = strlen(original_mysql_path_);
70       int mysql_data_home_len = strlen(mysql_data_home_path_);
71       if (len > mysql_data_home_len &&
72           !strncmp(original_mysql_path_,
73                    mysql_data_home_path_,
74                    mysql_data_home_len)) {
75         int i = mysql_data_home_len, j;
76         if (path_prefix_ && path_prefix_[0] == FN_LIBCHAR) {
77           strcpy(db_path_, path_prefix_);
78           j = strlen(db_path_);
79         } else {
80           memcpy(db_path_, mysql_data_home_path_, mysql_data_home_len);
81           if (path_prefix_) {
82             if (path_prefix_[0] == FN_CURLIB &&
83                 path_prefix_[1] == FN_LIBCHAR) {
84               strcpy(&db_path_[mysql_data_home_len], &path_prefix_[2]);
85             } else {
86               strcpy(&db_path_[mysql_data_home_len], path_prefix_);
87             }
88             j = strlen(db_path_);
89           } else {
90             j = mysql_data_home_len;
91           }
92         }
93 
94         while (original_mysql_path_[i] != FN_LIBCHAR && i < len) {
95           db_path_[j++] = original_mysql_path_[i++];
96         }
97         if (i == len) {
98           memcpy(db_path_, original_mysql_path_, len);
99         } else {
100           db_path_[j] = '\0';
101         }
102       } else {
103         strcpy(db_path_, original_mysql_path_);
104       }
105     } else {
106       strcpy(db_path_, original_mysql_path_);
107     }
108     strcat(db_path_, MRN_DB_FILE_SUFFIX);
109     return db_path_;
110   }
111 
112   /**
113    * "./${db}/${table}"                              ==> "${db}"
114    * "./${db}/"                                      ==> "${db}"
115    * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0" ==>
116    *   "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0"
117    */
db_name()118   const char *PathMapper::db_name() {
119     if (db_name_[0] != '\0') {
120       return db_name_;
121     }
122 
123     if (original_mysql_path_[0] == FN_CURLIB &&
124         original_mysql_path_[1] == FN_LIBCHAR) {
125       int i = 2, j = 0, len;
126       len = strlen(original_mysql_path_);
127       while (original_mysql_path_[i] != FN_LIBCHAR && i < len) {
128         db_name_[j++] = original_mysql_path_[i++];
129       }
130       db_name_[j] = '\0';
131     } else if (mysql_data_home_path_) {
132       int len = strlen(original_mysql_path_);
133       int mysql_data_home_len = strlen(mysql_data_home_path_);
134       if (len > mysql_data_home_len &&
135           !strncmp(original_mysql_path_,
136                    mysql_data_home_path_,
137                    mysql_data_home_len)) {
138         int i = mysql_data_home_len, j = 0;
139         while (original_mysql_path_[i] != FN_LIBCHAR && i < len) {
140           db_name_[j++] = original_mysql_path_[i++];
141         }
142         if (i == len) {
143           memcpy(db_name_, original_mysql_path_, len);
144         } else {
145           db_name_[j] = '\0';
146         }
147       } else {
148         strcpy(db_name_, original_mysql_path_);
149       }
150     } else {
151       strcpy(db_name_, original_mysql_path_);
152     }
153     return db_name_;
154   }
155 
156   /**
157    * "./${db}/${table}" ==> "${table}" (with encoding first '_')
158    */
table_name()159   const char *PathMapper::table_name() {
160     if (table_name_[0] != '\0') {
161       return table_name_;
162     }
163 
164     int len = strlen(original_mysql_path_);
165     int i = len, j = 0;
166     for (; original_mysql_path_[--i] != FN_LIBCHAR ;) {}
167     if (original_mysql_path_[i + 1] == '_') {
168       table_name_[j++] = '@';
169       table_name_[j++] = '0';
170       table_name_[j++] = '0';
171       table_name_[j++] = '5';
172       table_name_[j++] = 'f';
173       i++;
174     }
175     for (; i < len ;) {
176       table_name_[j++] = original_mysql_path_[++i];
177     }
178     table_name_[j] = '\0';
179     return table_name_;
180   }
181 
182   /**
183    * "./${db}/${table}" ==> "${table}" (without encoding first '_')
184    */
mysql_table_name()185   const char *PathMapper::mysql_table_name() {
186     if (mysql_table_name_[0] != '\0') {
187       return mysql_table_name_;
188     }
189 
190     int len = strlen(original_mysql_path_);
191     int i = len, j = 0;
192     for (; original_mysql_path_[--i] != FN_LIBCHAR ;) {}
193     for (; i < len ;) {
194       if (len - i - 1 >= 3 &&
195           strncmp(original_mysql_path_ + i + 1, "#P#", 3) == 0) {
196         break;
197       }
198       mysql_table_name_[j++] = original_mysql_path_[++i];
199     }
200     mysql_table_name_[j] = '\0';
201     return mysql_table_name_;
202   }
203 
204   /**
205    * "./${db}/${table}"       ==> "./${db}/${table}"
206    * "./${db}/${table}#P#xxx" ==> "./${db}/${table}"
207    */
mysql_path()208   const char *PathMapper::mysql_path() {
209     if (mysql_path_[0] != '\0') {
210       return mysql_path_;
211     }
212 
213     int i;
214     int len = strlen(original_mysql_path_);
215     for (i = 0; i < len; i++) {
216       if (len - i >= 3 &&
217           strncmp(original_mysql_path_ + i, "#P#", 3) == 0) {
218         break;
219       }
220       mysql_path_[i] = original_mysql_path_[i];
221     }
222     mysql_path_[i] = '\0';
223     return mysql_path_;
224   }
225 
is_internal_table_name()226   bool PathMapper::is_internal_table_name() {
227     return mysql_table_name()[0] == '#';
228   }
229 }
230