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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23
24 /**
25 @file
26
27 @brief
28 Read language depeneded messagefile
29 */
30
31 #include "sql_priv.h"
32 #include "unireg.h"
33 #include "derror.h"
34 #include "mysys_err.h"
35 #include "mysqld.h" // lc_messages_dir
36 #include "derror.h" // read_texts
37 #include "sql_class.h" // THD
38
39 static void init_myfunc_errs(void);
40
41
42 C_MODE_START
get_server_errmsgs()43 static const char **get_server_errmsgs()
44 {
45 if (!current_thd)
46 return DEFAULT_ERRMSGS;
47 return CURRENT_THD_ERRMSGS;
48 }
49 C_MODE_END
50
51 /**
52 Read messages from errorfile.
53
54 This function can be called multiple times to reload the messages.
55 If it fails to load the messages, it will fail softly by initializing
56 the errmesg pointer to an array of empty strings or by keeping the
57 old array if it exists.
58
59 @retval
60 FALSE OK
61 @retval
62 TRUE Error
63 */
64
init_errmessage(void)65 bool init_errmessage(void)
66 {
67 const char **errmsgs, **ptr;
68 DBUG_ENTER("init_errmessage");
69
70 /*
71 Get a pointer to the old error messages pointer array.
72 read_texts() tries to free it.
73 */
74 errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
75
76 /* Read messages from file. */
77 if (read_texts(ERRMSG_FILE, my_default_lc_messages->errmsgs->language,
78 &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1) &&
79 !errmsgs)
80 {
81 if (!(errmsgs= (const char**) my_malloc((ER_ERROR_LAST-ER_ERROR_FIRST+1)*
82 sizeof(char*), MYF(0))))
83 DBUG_RETURN(TRUE);
84 for (ptr= errmsgs; ptr < errmsgs + ER_ERROR_LAST - ER_ERROR_FIRST; ptr++)
85 *ptr= "";
86 }
87
88 /* Register messages for use with my_error(). */
89 if (my_error_register(get_server_errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST))
90 {
91 my_free(errmsgs);
92 DBUG_RETURN(TRUE);
93 }
94
95 DEFAULT_ERRMSGS= errmsgs; /* Init global variable */
96 init_myfunc_errs(); /* Init myfunc messages */
97 DBUG_RETURN(FALSE);
98 }
99
100
101 /**
102 Read text from packed textfile in language-directory.
103
104 If we can't read messagefile then it's panic- we can't continue.
105 */
106
read_texts(const char * file_name,const char * language,const char *** point,uint error_messages)107 bool read_texts(const char *file_name, const char *language,
108 const char ***point, uint error_messages)
109 {
110 uint i;
111 uint count,funktpos,textcount;
112 size_t length;
113 File file;
114 char name[FN_REFLEN];
115 char lang_path[FN_REFLEN];
116 uchar *buff;
117 uchar head[32],*pos;
118 DBUG_ENTER("read_texts");
119
120 LINT_INIT(buff);
121 funktpos=0;
122 convert_dirname(lang_path, language, NullS);
123 (void) my_load_path(lang_path, lang_path, lc_messages_dir);
124 if ((file= mysql_file_open(key_file_ERRMSG,
125 fn_format(name, file_name, lang_path, "", 4),
126 O_RDONLY | O_SHARE | O_BINARY,
127 MYF(0))) < 0)
128 {
129 /*
130 Trying pre-5.4 sematics of the --language parameter.
131 It included the language-specific part, e.g.:
132
133 --language=/path/to/english/
134 */
135 if ((file= mysql_file_open(key_file_ERRMSG,
136 fn_format(name, file_name, lc_messages_dir, "", 4),
137 O_RDONLY | O_SHARE | O_BINARY,
138 MYF(0))) < 0)
139 goto err;
140
141 sql_print_warning("Using pre 5.5 semantics to load error messages from %s.",
142 lc_messages_dir);
143
144 sql_print_warning("If this is not intended, refer to the documentation for "
145 "valid usage of --lc-messages-dir and --language "
146 "parameters.");
147 }
148
149 funktpos=1;
150 if (mysql_file_read(file, (uchar*) head, 32, MYF(MY_NABP)))
151 goto err;
152 if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
153 head[2] != 3 || head[3] != 1)
154 goto err; /* purecov: inspected */
155 textcount=head[4];
156
157 error_message_charset_info= system_charset_info;
158 length=uint4korr(head+6); count=uint4korr(head+10);
159
160 if (count < error_messages)
161 {
162 sql_print_error("\
163 Error message file '%s' had only %d error messages,\n\
164 but it should contain at least %d error messages.\n\
165 Check that the above file is the right version for this program!",
166 name,count,error_messages);
167 (void) mysql_file_close(file, MYF(MY_WME));
168 DBUG_RETURN(1);
169 }
170
171 /* Free old language */
172 my_free(*point);
173 if (!(*point= (const char**)
174 my_malloc((size_t) (length+count*sizeof(char*)),MYF(0))))
175 {
176 funktpos=2; /* purecov: inspected */
177 goto err; /* purecov: inspected */
178 }
179 buff= (uchar*) (*point + count);
180
181 if (mysql_file_read(file, buff, (size_t) count*4, MYF(MY_NABP)))
182 goto err;
183 for (i=0, pos= buff ; i< count ; i++)
184 {
185 (*point)[i]= (char*) buff+uint4korr(pos);
186 pos+=4;
187 }
188 if (mysql_file_read(file, buff, length, MYF(MY_NABP)))
189 goto err;
190
191 for (i=1 ; i < textcount ; i++)
192 {
193 point[i]= *point +uint2korr(head+10+i+i);
194 }
195 (void) mysql_file_close(file, MYF(0));
196 DBUG_RETURN(0);
197
198 err:
199 sql_print_error((funktpos == 2) ? "Not enough memory for messagefile '%s'" :
200 ((funktpos == 1) ? "Can't read from messagefile '%s'" :
201 "Can't find messagefile '%s'"), name);
202 if (file != FERR)
203 (void) mysql_file_close(file, MYF(MY_WME));
204 DBUG_RETURN(1);
205 } /* read_texts */
206
207
208 /**
209 Initiates error-messages used by my_func-library.
210 */
211
init_myfunc_errs()212 static void init_myfunc_errs()
213 {
214 init_glob_errs(); /* Initiate english errors */
215 if (!(specialflag & SPECIAL_ENGLISH))
216 {
217 EE(EE_FILENOTFOUND) = ER(ER_FILE_NOT_FOUND);
218 EE(EE_CANTCREATEFILE) = ER(ER_CANT_CREATE_FILE);
219 EE(EE_READ) = ER(ER_ERROR_ON_READ);
220 EE(EE_WRITE) = ER(ER_ERROR_ON_WRITE);
221 EE(EE_BADCLOSE) = ER(ER_ERROR_ON_CLOSE);
222 EE(EE_OUTOFMEMORY) = ER(ER_OUTOFMEMORY);
223 EE(EE_DELETE) = ER(ER_CANT_DELETE_FILE);
224 EE(EE_LINK) = ER(ER_ERROR_ON_RENAME);
225 EE(EE_EOFERR) = ER(ER_UNEXPECTED_EOF);
226 EE(EE_CANTLOCK) = ER(ER_CANT_LOCK);
227 EE(EE_DIR) = ER(ER_CANT_READ_DIR);
228 EE(EE_STAT) = ER(ER_CANT_GET_STAT);
229 EE(EE_GETWD) = ER(ER_CANT_GET_WD);
230 EE(EE_SETWD) = ER(ER_CANT_SET_WD);
231 EE(EE_DISK_FULL) = ER(ER_DISK_FULL);
232 }
233 }
234