MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
perror.c
1 /*
2  Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 
17 /* Return error-text for system error messages and handler messages */
18 
19 #define PERROR_VERSION "2.11"
20 
21 #include <my_global.h>
22 #include <my_sys.h>
23 #include <m_string.h>
24 #include <errno.h>
25 #include <my_getopt.h>
26 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
27 #include "../storage/ndb/src/ndbapi/ndberror.c"
28 #include "../storage/ndb/src/kernel/error/ndbd_exit_codes.c"
29 #include "../storage/ndb/include/mgmapi/mgmapi_error.h"
30 #endif
31 #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
32 
33 static my_bool verbose;
34 
35 #include "../include/my_base.h"
36 #include "../mysys/my_handler_errors.h"
37 
38 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
39 static my_bool ndb_code;
40 static char ndb_string[1024];
41 int mgmapi_error_string(int err_no, char *str, int size)
42 {
43  int i;
44  for (i= 0; i < ndb_mgm_noOfErrorMsgs; i++)
45  {
46  if ((int)ndb_mgm_error_msgs[i].code == err_no)
47  {
48  my_snprintf(str, size-1, "%s", ndb_mgm_error_msgs[i].msg);
49  str[size-1]= '\0';
50  return 0;
51  }
52  }
53  return -1;
54 }
55 #endif
56 
57 static struct my_option my_long_options[] =
58 {
59  {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG,
60  NO_ARG, 0, 0, 0, 0, 0, 0},
61  {"info", 'I', "Synonym for --help.", 0, 0, 0, GET_NO_ARG,
62  NO_ARG, 0, 0, 0, 0, 0, 0},
63 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
64  {"ndb", 257, "Ndbcluster storage engine specific error codes.", &ndb_code,
65  &ndb_code, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
66 #endif
67  {"silent", 's', "Only print the error message.", 0, 0, 0, GET_NO_ARG, NO_ARG,
68  0, 0, 0, 0, 0, 0},
69  {"verbose", 'v', "Print error code and message (default).", &verbose,
70  &verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
71  {"version", 'V', "Displays version information and exits.",
72  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
73  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
74 };
75 
76 
77 static void print_version(void)
78 {
79  printf("%s Ver %s, for %s (%s)\n",my_progname,PERROR_VERSION,
80  SYSTEM_TYPE,MACHINE_TYPE);
81 }
82 
83 
84 static void usage(void)
85 {
86  print_version();
87  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
88  printf("Print a description for a system error code or a MySQL error code.\n");
89  printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n");
90  printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname);
91  my_print_help(my_long_options);
92  my_print_variables(my_long_options);
93 }
94 
95 
96 static my_bool
97 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
98  char *argument __attribute__((unused)))
99 {
100  switch (optid) {
101  case 's':
102  verbose=0;
103  break;
104  case 'V':
105  print_version();
106  exit(0);
107  break;
108  case 'I':
109  case '?':
110  usage();
111  exit(0);
112  break;
113  }
114  return 0;
115 }
116 
117 
118 static int get_options(int *argc,char ***argv)
119 {
120  int ho_error;
121 
122  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
123  exit(ho_error);
124 
125  if (!*argc)
126  {
127  usage();
128  return 1;
129  }
130  return 0;
131 } /* get_options */
132 
133 
134 static const char *get_ha_error_msg(int code)
135 {
136  /*
137  If you got compilation error here about compile_time_assert array, check
138  that every HA_ERR_xxx constant has a corresponding error message in
139  handler_error_messages[] list (check mysys/my_handler_errors.h and
140  include/my_base.h).
141  */
142  compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
143  HA_ERR_LAST + 1);
144  if (code >= HA_ERR_FIRST && code <= HA_ERR_LAST)
145  return handler_error_messages[code - HA_ERR_FIRST];
146 
147  return NullS;
148 }
149 
150 typedef struct
151 {
152  const char *name;
153  uint code;
154  const char *text;
155 } st_error;
156 
157 static st_error global_error_names[] =
158 {
159 #include <mysqld_ername.h>
160  { 0, 0, 0 }
161 };
162 
170 int get_ER_error_msg(uint code, const char **name_ptr, const char **msg_ptr)
171 {
172  st_error *tmp_error;
173 
174  tmp_error= & global_error_names[0];
175 
176  while (tmp_error->name != NULL)
177  {
178  if (tmp_error->code == code)
179  {
180  *name_ptr= tmp_error->name;
181  *msg_ptr= tmp_error->text;
182  return 1;
183  }
184  tmp_error++;
185  }
186 
187  return 0;
188 }
189 
190 #if defined(__WIN__)
191 static my_bool print_win_error_msg(DWORD error, my_bool verbose)
192 {
193  LPTSTR s;
194  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
195  FORMAT_MESSAGE_FROM_SYSTEM,
196  NULL, error, 0, (LPTSTR)&s, 0,
197  NULL))
198  {
199  if (verbose)
200  printf("Win32 error code %d: %s", error, s);
201  else
202  puts(s);
203  LocalFree(s);
204  return 0;
205  }
206  return 1;
207 }
208 #endif
209 
210 /*
211  Register handler error messages for usage with my_error()
212 
213  NOTES
214  This is safe to call multiple times as my_error_register()
215  will ignore calls to register already registered error numbers.
216 */
217 
218 static const char **get_handler_error_messages()
219 {
220  return handler_error_messages;
221 }
222 
223 void my_handler_error_register(void)
224 {
225  /*
226  If you got compilation error here about compile_time_assert array, check
227  that every HA_ERR_xxx constant has a corresponding error message in
228  handler_error_messages[] list (check mysys/ma_handler_errors.h and
229  include/my_base.h).
230  */
231  compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
232  HA_ERR_LAST + 1);
233  my_error_register(get_handler_error_messages, HA_ERR_FIRST,
234  HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
235 }
236 
237 
238 void my_handler_error_unregister(void)
239 {
240  my_error_unregister(HA_ERR_FIRST,
241  HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
242 }
243 
244 int main(int argc,char *argv[])
245 {
246  int error,code,found;
247  const char *msg;
248  const char *name;
249  char *unknown_error = 0;
250 #if defined(__WIN__)
251  my_bool skip_win_message= 0;
252 #endif
253  MY_INIT(argv[0]);
254 
255  if (get_options(&argc,&argv))
256  exit(1);
257 
258  my_handler_error_register();
259 
260  error=0;
261  {
262  /*
263  On some system, like Linux, strerror(unknown_error) returns a
264  string 'Unknown Error'. To avoid printing it we try to find the
265  error string by asking for an impossible big error message.
266 
267  On Solaris 2.8 it might return NULL
268  */
269  if ((msg= strerror(10000)) == NULL)
270  msg= "Unknown Error";
271 
272  /*
273  Allocate a buffer for unknown_error since strerror always returns
274  the same pointer on some platforms such as Windows
275  */
276  unknown_error= malloc(strlen(msg)+1);
277  strmov(unknown_error, msg);
278 
279  for ( ; argc-- > 0 ; argv++)
280  {
281 
282  found=0;
283  code=atoi(*argv);
284 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
285  if (ndb_code)
286  {
287  if ((ndb_error_string(code, ndb_string, sizeof(ndb_string)) < 0) &&
288  (ndbd_exit_string(code, ndb_string, sizeof(ndb_string)) < 0) &&
289  (mgmapi_error_string(code, ndb_string, sizeof(ndb_string)) < 0))
290  {
291  msg= 0;
292  }
293  else
294  msg= ndb_string;
295  if (msg)
296  {
297  if (verbose)
298  printf("NDB error code %3d: %s\n",code,msg);
299  else
300  puts(msg);
301  }
302  else
303  {
304  fprintf(stderr,"Illegal ndb error code: %d\n",code);
305  error= 1;
306  }
307  found= 1;
308  msg= 0;
309  }
310  else
311 #endif
312  msg = strerror(code);
313 
314  /*
315  We don't print the OS error message if it is the same as the
316  unknown_error message we retrieved above, or it starts with
317  'Unknown Error' (without regard to case).
318  */
319  if (msg &&
320  my_strnncoll(&my_charset_latin1, (const uchar*) msg, 13,
321  (const uchar*) "Unknown Error", 13) &&
322  (!unknown_error || strcmp(msg, unknown_error)))
323  {
324  found= 1;
325  if (verbose)
326  printf("OS error code %3d: %s\n", code, msg);
327  else
328  puts(msg);
329  }
330  if ((msg= get_ha_error_msg(code)))
331  {
332  found= 1;
333  if (verbose)
334  printf("MySQL error code %3d: %s\n", code, msg);
335  else
336  puts(msg);
337  }
338  if (get_ER_error_msg(code, & name, & msg))
339  {
340  found= 1;
341  if (verbose)
342  printf("MySQL error code %3d (%s): %s\n", code, name, msg);
343  else
344  puts(msg);
345  }
346  if (!found)
347  {
348 #if defined(__WIN__)
349  if (!(skip_win_message= !print_win_error_msg((DWORD)code, verbose)))
350  {
351 #endif
352  fprintf(stderr,"Illegal error code: %d\n",code);
353  error=1;
354 #if defined(__WIN__)
355  }
356 #endif
357  }
358 #if defined(__WIN__)
359  if (!skip_win_message)
360  print_win_error_msg((DWORD)code, verbose);
361 #endif
362  }
363  }
364 
365  /* if we allocated a buffer for unknown_error, free it now */
366  if (unknown_error)
367  free(unknown_error);
368 
369  exit(error);
370  return error;
371 }