2001-12-06 13:10:51 +01:00
/* Copyright (C) 2000 MySQL AB
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2006-12-23 20:17:15 +01:00
the Free Software Foundation ; version 2 of the License .
2001-12-06 13:10:51 +01:00
This program is distributed in the hope that it will be useful ,
2000-07-31 21:29:14 +02:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2001-12-06 13:10:51 +01:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA */
2000-07-31 21:29:14 +02:00
2008-03-28 17:45:03 +01:00
/* Return error-text for system error messages and handler messages */
2000-07-31 21:29:14 +02:00
2008-03-28 17:45:03 +01:00
# define PERROR_VERSION "2.11"
2000-07-31 21:29:14 +02:00
2001-09-14 01:54:33 +02:00
# include <my_global.h>
2000-07-31 21:29:14 +02:00
# include <my_sys.h>
# include <m_string.h>
# include <errno.h>
2002-05-22 22:54:24 +02:00
# include <my_getopt.h>
2005-12-05 14:17:53 +01:00
# ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2005-04-27 04:04:36 +02:00
# include "../storage/ndb/src/ndbapi/ndberror.c"
2005-10-07 01:12:46 +02:00
# include "../storage/ndb/src/kernel/error/ndbd_exit_codes.c"
2007-06-14 12:35:35 +02:00
# include "../storage/ndb/include/mgmapi/mgmapi_error.h"
2004-05-05 14:19:47 +02:00
# endif
2000-07-31 21:29:14 +02:00
2002-05-22 22:54:24 +02:00
static my_bool verbose , print_all_codes ;
2000-07-31 21:29:14 +02:00
2008-03-28 17:45:03 +01:00
# include "../include/my_base.h"
# include "../mysys/my_handler_errors.h"
2008-03-28 20:59:20 +01:00
# include "../include/my_handler.h"
2008-03-28 17:45:03 +01:00
2005-12-05 14:17:53 +01:00
# ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2004-05-05 14:19:47 +02:00
static my_bool ndb_code ;
static char ndb_string [ 1024 ] ;
2007-06-14 12:35:35 +02:00
int mgmapi_error_string ( int err_no , char * str , int size )
{
int i ;
for ( i = 0 ; i < ndb_mgm_noOfErrorMsgs ; i + + )
{
2007-06-14 15:15:45 +02:00
if ( ( int ) ndb_mgm_error_msgs [ i ] . code = = err_no )
2007-06-14 12:35:35 +02:00
{
my_snprintf ( str , size - 1 , " %s " , ndb_mgm_error_msgs [ i ] . msg ) ;
str [ size - 1 ] = ' \0 ' ;
return 0 ;
}
}
return - 1 ;
}
2004-05-05 14:19:47 +02:00
# endif
2002-05-22 22:54:24 +02:00
static struct my_option my_long_options [ ] =
2000-07-31 21:29:14 +02:00
{
2002-05-22 22:54:24 +02:00
{ " help " , ' ? ' , " Displays this help and exits. " , 0 , 0 , 0 , GET_NO_ARG ,
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2003-06-13 10:59:02 +02:00
{ " info " , ' I ' , " Synonym for --help. " , 0 , 0 , 0 , GET_NO_ARG ,
2002-05-22 22:54:24 +02:00
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2005-12-05 14:17:53 +01:00
# ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2010-06-10 22:16:43 +02:00
{ " ndb " , 257 , " Ndbcluster storage engine specific error codes. " , & ndb_code ,
& ndb_code , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2004-05-05 14:19:47 +02:00
# endif
2002-05-22 22:54:24 +02:00
# ifdef HAVE_SYS_ERRLIST
{ " all " , ' a ' , " Print all the error messages and the number. " ,
2010-06-10 22:16:43 +02:00
& print_all_codes , & print_all_codes , 0 , GET_BOOL , NO_ARG ,
2002-05-22 22:54:24 +02:00
0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
2003-06-13 10:59:02 +02:00
{ " silent " , ' s ' , " Only print the error message. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG ,
2002-05-22 22:54:24 +02:00
0 , 0 , 0 , 0 , 0 , 0 } ,
2010-06-10 22:16:43 +02:00
{ " verbose " , ' v ' , " Print error code and message (default). " , & verbose ,
& verbose , 0 , GET_BOOL , NO_ARG , 1 , 0 , 0 , 0 , 0 , 0 } ,
2002-05-22 22:54:24 +02:00
{ " version " , ' V ' , " Displays version information and exits. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 }
2000-07-31 21:29:14 +02:00
} ;
2002-05-22 22:54:24 +02:00
2000-07-31 21:29:14 +02:00
typedef struct ha_errors {
int errcode ;
const char * msg ;
} HA_ERRORS ;
static HA_ERRORS ha_errlist [ ] =
{
2001-09-18 03:58:15 +02:00
{ - 30999 , " DB_INCOMPLETE: Sync didn't finish " } ,
{ - 30998 , " DB_KEYEMPTY: Key/data deleted or never created " } ,
{ - 30997 , " DB_KEYEXIST: The key/data pair already exists " } ,
{ - 30996 , " DB_LOCK_DEADLOCK: Deadlock " } ,
{ - 30995 , " DB_LOCK_NOTGRANTED: Lock unavailable " } ,
{ - 30994 , " DB_NOSERVER: Server panic return " } ,
{ - 30993 , " DB_NOSERVER_HOME: Bad home sent to server " } ,
{ - 30992 , " DB_NOSERVER_ID: Bad ID sent to server " } ,
{ - 30991 , " DB_NOTFOUND: Key/data pair not found (EOF) " } ,
{ - 30990 , " DB_OLD_VERSION: Out-of-date version " } ,
{ - 30989 , " DB_RUNRECOVERY: Panic return " } ,
{ - 30988 , " DB_VERIFY_BAD: Verify failed; bad format " } ,
2000-07-31 21:29:14 +02:00
{ 0 , NullS } ,
} ;
static void print_version ( void )
{
printf ( " %s Ver %s, for %s (%s) \n " , my_progname , PERROR_VERSION ,
SYSTEM_TYPE , MACHINE_TYPE ) ;
}
2005-02-08 18:49:40 +01:00
2000-07-31 21:29:14 +02:00
static void usage ( void )
{
print_version ( ) ;
puts ( " This software comes with ABSOLUTELY NO WARRANTY. This is free software, \n and you are welcome to modify and redistribute it under the GPL license \n " ) ;
2009-04-28 20:16:44 +02:00
printf ( " Print a description for a system error code or a MySQL error code. \n " ) ;
2001-09-18 03:58:15 +02:00
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 " ) ;
2000-10-10 23:48:03 +02:00
printf ( " Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]] \n " , my_progname ) ;
2002-05-22 22:54:24 +02:00
my_print_help ( my_long_options ) ;
my_print_variables ( my_long_options ) ;
}
static my_bool
get_one_option ( int optid , const struct my_option * opt __attribute__ ( ( unused ) ) ,
char * argument __attribute__ ( ( unused ) ) )
{
switch ( optid ) {
case ' s ' :
verbose = 0 ;
break ;
case ' V ' :
print_version ( ) ;
exit ( 0 ) ;
break ;
case ' I ' :
case ' ? ' :
usage ( ) ;
exit ( 0 ) ;
break ;
}
return 0 ;
2001-12-06 13:10:51 +01:00
}
2000-07-31 21:29:14 +02:00
static int get_options ( int * argc , char * * * argv )
{
2002-05-22 22:54:24 +02:00
int ho_error ;
2000-07-31 21:29:14 +02:00
2004-08-31 18:27:58 +02:00
if ( ( ho_error = handle_options ( argc , argv , my_long_options , get_one_option ) ) )
2002-05-29 14:07:30 +02:00
exit ( ho_error ) ;
2000-07-31 21:29:14 +02:00
if ( ! * argc & & ! print_all_codes )
{
usage ( ) ;
return 1 ;
}
return 0 ;
} /* get_options */
static const char * get_ha_error_msg ( int code )
{
HA_ERRORS * ha_err_ptr ;
2008-03-28 17:45:03 +01:00
/*
If you got compilation error here about compile_time_assert array , check
that every HA_ERR_xxx constant has a corresponding error message in
handler_error_messages [ ] list ( check mysys / ma_handler_errors . h and
include / my_base . h ) .
*/
compile_time_assert ( HA_ERR_FIRST + array_elements ( handler_error_messages ) = =
HA_ERR_LAST + 1 ) ;
if ( code > = HA_ERR_FIRST & & code < = HA_ERR_LAST )
return handler_error_messages [ code - HA_ERR_FIRST ] ;
2000-07-31 21:29:14 +02:00
for ( ha_err_ptr = ha_errlist ; ha_err_ptr - > errcode ; ha_err_ptr + + )
if ( ha_err_ptr - > errcode = = code )
return ha_err_ptr - > msg ;
return NullS ;
}
2010-02-24 01:45:49 +01:00
typedef struct
{
const char * name ;
uint code ;
const char * text ;
} st_error ;
static st_error global_error_names [ ] =
{
# include <mysqld_ername.h>
{ 0 , 0 , 0 }
} ;
/**
Lookup an error by code in the global_error_names array .
@ param code the code to lookup
@ param [ out ] name_ptr the error name , when found
@ param [ out ] msg_ptr the error text , when found
@ return 1 when found , otherwise 0
*/
int get_ER_error_msg ( uint code , const char * * name_ptr , const char * * msg_ptr )
{
st_error * tmp_error ;
tmp_error = & global_error_names [ 0 ] ;
while ( tmp_error - > name ! = NULL )
{
if ( tmp_error - > code = = code )
{
* name_ptr = tmp_error - > name ;
* msg_ptr = tmp_error - > text ;
return 1 ;
}
tmp_error + + ;
}
return 0 ;
}
2000-07-31 21:29:14 +02:00
2008-11-27 13:33:40 +01:00
# if defined(__WIN__)
static my_bool print_win_error_msg ( DWORD error , my_bool verbose )
{
LPTSTR s ;
if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM ,
NULL , error , 0 , ( LPTSTR ) & s , 0 ,
NULL ) )
{
if ( verbose )
printf ( " Win32 error code %d: %s " , error , s ) ;
else
puts ( s ) ;
LocalFree ( s ) ;
return 0 ;
}
return 1 ;
}
# endif
2000-07-31 21:29:14 +02:00
int main ( int argc , char * argv [ ] )
{
int error , code , found ;
const char * msg ;
2010-02-24 01:45:49 +01:00
const char * name ;
2005-02-01 06:02:32 +01:00
char * unknown_error = 0 ;
2008-11-27 13:33:40 +01:00
# if defined(__WIN__)
my_bool skip_win_message = 0 ;
# endif
2000-07-31 21:29:14 +02:00
MY_INIT ( argv [ 0 ] ) ;
if ( get_options ( & argc , & argv ) )
exit ( 1 ) ;
2008-03-28 17:45:03 +01:00
my_handler_error_register ( ) ;
2000-07-31 21:29:14 +02:00
error = 0 ;
# ifdef HAVE_SYS_ERRLIST
if ( print_all_codes )
{
HA_ERRORS * ha_err_ptr ;
for ( code = 1 ; code < sys_nerr ; code + + )
{
2010-05-26 16:12:23 +02:00
if ( sys_errlist [ code ] & & sys_errlist [ code ] [ 0 ] )
2004-06-03 18:52:54 +02:00
{ /* Skip if no error-text */
2000-07-31 21:29:14 +02:00
printf ( " %3d = %s \n " , code , sys_errlist [ code ] ) ;
}
}
for ( ha_err_ptr = ha_errlist ; ha_err_ptr - > errcode ; ha_err_ptr + + )
printf ( " %3d = %s \n " , ha_err_ptr - > errcode , ha_err_ptr - > msg ) ;
}
else
# endif
{
2004-05-25 21:00:14 +02:00
/*
2010-07-15 13:13:30 +02:00
On some system , like Linux , strerror ( unknown_error ) returns a
2004-05-25 21:00:14 +02:00
string ' Unknown Error ' . To avoid printing it we try to find the
error string by asking for an impossible big error message .
2006-07-24 18:05:00 +02:00
On Solaris 2.8 it might return NULL
2004-05-25 21:00:14 +02:00
*/
2006-07-24 18:05:00 +02:00
if ( ( msg = strerror ( 10000 ) ) = = NULL )
msg = " Unknown Error " ;
2005-02-01 06:02:32 +01:00
2005-02-02 19:28:01 +01:00
/*
Allocate a buffer for unknown_error since strerror always returns
the same pointer on some platforms such as Windows
*/
unknown_error = malloc ( strlen ( msg ) + 1 ) ;
strmov ( unknown_error , msg ) ;
2004-05-25 21:00:14 +02:00
2000-07-31 21:29:14 +02:00
for ( ; argc - - > 0 ; argv + + )
{
2004-05-25 21:54:00 +02:00
2000-07-31 21:29:14 +02:00
found = 0 ;
code = atoi ( * argv ) ;
2005-12-05 14:17:53 +01:00
# ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2004-05-05 14:19:47 +02:00
if ( ndb_code )
{
2007-06-14 12:35:35 +02:00
if ( ( ndb_error_string ( code , ndb_string , sizeof ( ndb_string ) ) < 0 ) & &
( ndbd_exit_string ( code , ndb_string , sizeof ( ndb_string ) ) < 0 ) & &
( mgmapi_error_string ( code , ndb_string , sizeof ( ndb_string ) ) < 0 ) )
2005-10-03 20:04:44 +02:00
{
2006-02-08 17:17:27 +01:00
msg = 0 ;
2005-10-03 20:04:44 +02:00
}
2004-05-05 14:19:47 +02:00
else
msg = ndb_string ;
2006-02-08 17:17:27 +01:00
if ( msg )
{
if ( verbose )
printf ( " NDB error code %3d: %s \n " , code , msg ) ;
else
puts ( msg ) ;
}
else
{
fprintf ( stderr , " Illegal ndb error code: %d \n " , code ) ;
error = 1 ;
}
found = 1 ;
msg = 0 ;
2004-05-05 14:19:47 +02:00
}
2006-07-26 14:09:20 +02:00
else
2004-05-05 14:19:47 +02:00
# endif
msg = strerror ( code ) ;
2004-05-25 21:00:14 +02:00
/*
2005-02-17 02:37:56 +01:00
We don ' t print the OS error message if it is the same as the
unknown_error message we retrieved above , or it starts with
' Unknown Error ' ( without regard to case ) .
2004-05-25 21:00:14 +02:00
*/
2005-02-17 02:37:56 +01:00
if ( msg & &
2005-02-25 15:53:22 +01:00
my_strnncoll ( & my_charset_latin1 , ( const uchar * ) msg , 13 ,
( const uchar * ) " Unknown Error " , 13 ) & &
2004-05-25 21:00:14 +02:00
( ! unknown_error | | strcmp ( msg , unknown_error ) ) )
2000-07-31 21:29:14 +02:00
{
2008-03-28 17:45:03 +01:00
found = 1 ;
2000-07-31 21:29:14 +02:00
if ( verbose )
2008-03-28 17:45:03 +01:00
printf ( " OS error code %3d: %s \n " , code , msg ) ;
2000-07-31 21:29:14 +02:00
else
puts ( msg ) ;
}
2008-03-28 17:45:03 +01:00
if ( ( msg = get_ha_error_msg ( code ) ) )
2000-07-31 21:29:14 +02:00
{
2008-03-28 17:45:03 +01:00
found = 1 ;
if ( verbose )
printf ( " MySQL error code %3d: %s \n " , code , msg ) ;
2006-07-26 14:09:20 +02:00
else
2008-03-28 17:45:03 +01:00
puts ( msg ) ;
}
2010-02-24 01:45:49 +01:00
if ( get_ER_error_msg ( code , & name , & msg ) )
{
found = 1 ;
if ( verbose )
printf ( " MySQL error code %3d (%s): %s \n " , code , name , msg ) ;
else
puts ( msg ) ;
}
2008-03-28 17:45:03 +01:00
if ( ! found )
{
2008-11-27 13:33:40 +01:00
# if defined(__WIN__)
2008-11-27 14:05:38 +01:00
if ( ! ( skip_win_message = ! print_win_error_msg ( ( DWORD ) code , verbose ) ) )
{
2008-11-27 13:33:40 +01:00
# endif
2008-11-27 14:05:38 +01:00
fprintf ( stderr , " Illegal error code: %d \n " , code ) ;
error = 1 ;
2008-11-27 13:33:40 +01:00
# if defined(__WIN__)
2006-07-26 14:09:20 +02:00
}
2008-11-27 14:05:38 +01:00
# endif
2000-07-31 21:29:14 +02:00
}
2008-11-27 13:33:40 +01:00
# if defined(__WIN__)
if ( ! skip_win_message )
print_win_error_msg ( ( DWORD ) code , verbose ) ;
# endif
2000-07-31 21:29:14 +02:00
}
}
2005-02-01 06:02:32 +01:00
/* if we allocated a buffer for unknown_error, free it now */
if ( unknown_error )
2005-02-02 19:28:01 +01:00
free ( unknown_error ) ;
2005-02-01 06:02:32 +01:00
2000-07-31 21:29:14 +02:00
exit ( error ) ;
return error ;
}