1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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 /**
17 @file
18
19 @brief
20 Read language depeneded messagefile
21 */
22
23 #include "sql_priv.h"
24 #include "unireg.h"
25 #include "derror.h"
26 #include "mysys_err.h"
27 #include "mysqld.h" // lc_messages_dir
28 #include "derror.h" // read_texts
29 #include "sql_class.h" // THD
30
31 static void init_myfunc_errs(void);
32
33
34 C_MODE_START
get_server_errmsgs()35 static const char **get_server_errmsgs()
36 {
37 if (!current_thd)
38 return DEFAULT_ERRMSGS;
39 return CURRENT_THD_ERRMSGS;
40 }
41 C_MODE_END
42
43 /**
44 Read messages from errorfile.
45
46 This function can be called multiple times to reload the messages.
47 If it fails to load the messages, it will fail softly by initializing
48 the errmesg pointer to an array of empty strings or by keeping the
49 old array if it exists.
50
51 @retval
52 FALSE OK
53 @retval
54 TRUE Error
55 */
56
init_errmessage(void)57 bool init_errmessage(void)
58 {
59 const char **errmsgs, **ptr;
60 DBUG_ENTER("init_errmessage");
61
62 /*
63 Get a pointer to the old error messages pointer array.
64 read_texts() tries to free it.
65 */
66 errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
67
68 /* Read messages from file. */
69 if (read_texts(ERRMSG_FILE, my_default_lc_messages->errmsgs->language,
70 &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1) &&
71 !errmsgs)
72 {
73 if (!(errmsgs= (const char**) my_malloc((ER_ERROR_LAST-ER_ERROR_FIRST+1)*
74 sizeof(char*), MYF(0))))
75 DBUG_RETURN(TRUE);
76 for (ptr= errmsgs; ptr < errmsgs + ER_ERROR_LAST - ER_ERROR_FIRST; ptr++)
77 *ptr= "";
78 }
79
80 /* Register messages for use with my_error(). */
81 if (my_error_register(get_server_errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST))
82 {
83 my_free(errmsgs);
84 DBUG_RETURN(TRUE);
85 }
86
87 DEFAULT_ERRMSGS= errmsgs; /* Init global variable */
88 init_myfunc_errs(); /* Init myfunc messages */
89 DBUG_RETURN(FALSE);
90 }
91
92
93 /**
94 Read text from packed textfile in language-directory.
95
96 If we can't read messagefile then it's panic- we can't continue.
97 */
98
read_texts(const char * file_name,const char * language,const char *** point,uint error_messages)99 bool read_texts(const char *file_name, const char *language,
100 const char ***point, uint error_messages)
101 {
102 register uint i;
103 uint count,funktpos,textcount;
104 size_t length;
105 File file;
106 char name[FN_REFLEN];
107 char lang_path[FN_REFLEN];
108 uchar *buff;
109 uchar head[32],*pos;
110 DBUG_ENTER("read_texts");
111
112 LINT_INIT(buff);
113 funktpos=0;
114 convert_dirname(lang_path, language, NullS);
115 (void) my_load_path(lang_path, lang_path, lc_messages_dir);
116 if ((file= mysql_file_open(key_file_ERRMSG,
117 fn_format(name, file_name, lang_path, "", 4),
118 O_RDONLY | O_SHARE | O_BINARY,
119 MYF(0))) < 0)
120 {
121 /*
122 Trying pre-5.4 sematics of the --language parameter.
123 It included the language-specific part, e.g.:
124
125 --language=/path/to/english/
126 */
127 if ((file= mysql_file_open(key_file_ERRMSG,
128 fn_format(name, file_name, lc_messages_dir, "", 4),
129 O_RDONLY | O_SHARE | O_BINARY,
130 MYF(0))) < 0)
131 goto err;
132 sql_print_error("An old style --language value with language specific part detected: %s", lc_messages_dir);
133 sql_print_error("Use --lc-messages-dir without language specific part instead.");
134 }
135
136 funktpos=1;
137 if (mysql_file_read(file, (uchar*) head, 32, MYF(MY_NABP)))
138 goto err;
139 if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
140 head[2] != 2 || head[3] != 1)
141 goto err; /* purecov: inspected */
142 textcount=head[4];
143
144 error_message_charset_info= system_charset_info;
145 length=uint2korr(head+6); count=uint2korr(head+8);
146
147 if (count < error_messages)
148 {
149 sql_print_error("\
150 Error message file '%s' had only %d error messages,\n\
151 but it should contain at least %d error messages.\n\
152 Check that the above file is the right version for this program!",
153 name,count,error_messages);
154 (void) mysql_file_close(file, MYF(MY_WME));
155 DBUG_RETURN(1);
156 }
157
158 /* Free old language */
159 my_free(*point);
160 if (!(*point= (const char**)
161 my_malloc((size_t) (length+count*sizeof(char*)),MYF(0))))
162 {
163 funktpos=2; /* purecov: inspected */
164 goto err; /* purecov: inspected */
165 }
166 buff= (uchar*) (*point + count);
167
168 if (mysql_file_read(file, buff, (size_t) count*2, MYF(MY_NABP)))
169 goto err;
170 for (i=0, pos= buff ; i< count ; i++)
171 {
172 (*point)[i]= (char*) buff+uint2korr(pos);
173 pos+=2;
174 }
175 if (mysql_file_read(file, buff, length, MYF(MY_NABP)))
176 goto err;
177
178 for (i=1 ; i < textcount ; i++)
179 {
180 point[i]= *point +uint2korr(head+10+i+i);
181 }
182 (void) mysql_file_close(file, MYF(0));
183 DBUG_RETURN(0);
184
185 err:
186 sql_print_error((funktpos == 2) ? "Not enough memory for messagefile '%s'" :
187 ((funktpos == 1) ? "Can't read from messagefile '%s'" :
188 "Can't find messagefile '%s'"), name);
189 if (file != FERR)
190 (void) mysql_file_close(file, MYF(MY_WME));
191 DBUG_RETURN(1);
192 } /* read_texts */
193
194
195 /**
196 Initiates error-messages used by my_func-library.
197 */
198
init_myfunc_errs()199 static void init_myfunc_errs()
200 {
201 init_glob_errs(); /* Initiate english errors */
202 if (!(specialflag & SPECIAL_ENGLISH))
203 {
204 EE(EE_FILENOTFOUND) = ER(ER_FILE_NOT_FOUND);
205 EE(EE_CANTCREATEFILE) = ER(ER_CANT_CREATE_FILE);
206 EE(EE_READ) = ER(ER_ERROR_ON_READ);
207 EE(EE_WRITE) = ER(ER_ERROR_ON_WRITE);
208 EE(EE_BADCLOSE) = ER(ER_ERROR_ON_CLOSE);
209 EE(EE_OUTOFMEMORY) = ER(ER_OUTOFMEMORY);
210 EE(EE_DELETE) = ER(ER_CANT_DELETE_FILE);
211 EE(EE_LINK) = ER(ER_ERROR_ON_RENAME);
212 EE(EE_EOFERR) = ER(ER_UNEXPECTED_EOF);
213 EE(EE_CANTLOCK) = ER(ER_CANT_LOCK);
214 EE(EE_DIR) = ER(ER_CANT_READ_DIR);
215 EE(EE_STAT) = ER(ER_CANT_GET_STAT);
216 EE(EE_GETWD) = ER(ER_CANT_GET_WD);
217 EE(EE_SETWD) = ER(ER_CANT_SET_WD);
218 EE(EE_DISK_FULL) = ER(ER_DISK_FULL);
219 }
220 }
221