2011-06-30 17:37:13 +02:00
|
|
|
/*
|
2011-07-03 17:47:37 +02:00
|
|
|
Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
2002-01-25 23:34:37 +02:00
|
|
|
|
|
|
|
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.
|
2002-01-25 23:34:37 +02:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
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
|
2011-06-30 17:37:13 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2002-01-25 23:34:37 +02:00
|
|
|
|
2004-08-18 22:31:01 +02:00
|
|
|
#ifndef _my_getopt_h
|
|
|
|
#define _my_getopt_h
|
|
|
|
|
2002-04-02 20:29:53 +03:00
|
|
|
C_MODE_START
|
2002-01-25 23:34:37 +02:00
|
|
|
|
2004-07-08 17:12:42 +03:00
|
|
|
#define GET_NO_ARG 1
|
|
|
|
#define GET_BOOL 2
|
|
|
|
#define GET_INT 3
|
|
|
|
#define GET_UINT 4
|
|
|
|
#define GET_LONG 5
|
|
|
|
#define GET_ULONG 6
|
|
|
|
#define GET_LL 7
|
|
|
|
#define GET_ULL 8
|
|
|
|
#define GET_STR 9
|
|
|
|
#define GET_STR_ALLOC 10
|
2004-07-09 02:29:28 +03:00
|
|
|
#define GET_DISABLED 11
|
2007-03-02 08:43:45 -08:00
|
|
|
#define GET_ENUM 12
|
|
|
|
#define GET_SET 13
|
2007-07-30 11:33:50 +03:00
|
|
|
#define GET_DOUBLE 14
|
2003-06-27 18:51:39 +03:00
|
|
|
|
2004-01-14 04:58:37 +02:00
|
|
|
#define GET_ASK_ADDR 128
|
|
|
|
#define GET_TYPE_MASK 127
|
2003-06-27 18:51:39 +03:00
|
|
|
|
2002-01-25 23:34:37 +02:00
|
|
|
enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
|
|
|
|
|
2007-03-02 08:43:45 -08:00
|
|
|
struct st_typelib;
|
|
|
|
|
2002-01-25 23:34:37 +02:00
|
|
|
struct my_option
|
|
|
|
{
|
|
|
|
const char *name; /* Name of the option */
|
2002-04-02 20:29:53 +03:00
|
|
|
int id; /* unique id or short option */
|
2002-01-25 23:34:37 +02:00
|
|
|
const char *comment; /* option comment, for autom. --help */
|
2010-06-10 17:16:43 -03:00
|
|
|
void *value; /* The variable value */
|
|
|
|
void *u_max_value; /* The user def. max variable value */
|
2007-03-02 08:43:45 -08:00
|
|
|
struct st_typelib *typelib; /* Pointer to possible values */
|
2010-06-10 17:16:43 -03:00
|
|
|
ulong var_type; /* Must match the variable type */
|
2002-01-25 23:34:37 +02:00
|
|
|
enum get_opt_arg_type arg_type;
|
2002-01-29 18:32:16 +02:00
|
|
|
longlong def_value; /* Default value */
|
|
|
|
longlong min_value; /* Min allowed value */
|
|
|
|
longlong max_value; /* Max allowed value */
|
|
|
|
longlong sub_size; /* Subtract this from given value */
|
2002-01-25 23:34:37 +02:00
|
|
|
long block_size; /* Value should be a mult. of this */
|
2007-03-23 10:14:46 -07:00
|
|
|
void *app_type; /* To be used by an application */
|
2002-01-25 23:34:37 +02:00
|
|
|
};
|
|
|
|
|
2010-06-10 17:16:43 -03:00
|
|
|
typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *);
|
Fix for BUG#11755168 '46895: test "outfile_loaddata" fails (reproducible)'.
In sql_class.cc, 'row_count', of type 'ha_rows', was used as last argument for
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD which is
"Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld".
So 'ha_rows' was used as 'long'.
On SPARC32 Solaris builds, 'long' is 4 bytes and 'ha_rows' is 'longlong' i.e. 8 bytes.
So the printf-like code was reading only the first 4 bytes.
Because the CPU is big-endian, 1LL is 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
so the first four bytes yield 0. So the warning message had "row 0" instead of
"row 1" in test outfile_loaddata.test:
-Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 1
+Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 0
All error-messaging functions which internally invoke some printf-life function
are potential candidate for such mistakes.
One apparently easy way to catch such mistakes is to use
ATTRIBUTE_FORMAT (from my_attribute.h).
But this works only when call site has both:
a) the format as a string literal
b) the types of arguments.
So:
func(ER(ER_BLAH), 10);
will silently not be checked, because ER(ER_BLAH) is not known at
compile time (it is known at run-time, and depends on the chosen
language).
And
func("%s", a va_list argument);
has the same problem, as the *real* type of arguments is not
known at this site at compile time (it's known in some caller).
Moreover,
func(ER(ER_BLAH));
though possibly correct (if ER(ER_BLAH) has no '%' markers), will not
compile (gcc says "error: format not a string literal and no format
arguments").
Consequences:
1) ATTRIBUTE_FORMAT is here added only to functions which in practice
take "string literal" formats: "my_error_reporter" and "print_admin_msg".
2) it cannot be added to the other functions: my_error(),
push_warning_printf(), Table_check_intact::report_error(),
general_log_print().
To do a one-time check of functions listed in (2), the following
"static code analysis" has been done:
1) replace
my_error(ER_xxx, arguments for substitution in format)
with the equivalent
my_printf_error(ER_xxx,ER(ER_xxx), arguments for substitution in
format),
so that we have ER(ER_xxx) and the arguments *in the same call site*
2) add ATTRIBUTE_FORMAT to push_warning_printf(),
Table_check_intact::report_error(), general_log_print()
3) replace ER(xxx) with the hard-coded English text found in
errmsg.txt (like: ER(ER_UNKNOWN_ERROR) is replaced with
"Unknown error"), so that a call site has the format as string literal
4) this way, ATTRIBUTE_FORMAT can effectively do its job
5) compile, fix errors detected by ATTRIBUTE_FORMAT
6) revert steps 1-2-3.
The present patch has no compiler error when submitted again to the
static code analysis above.
It cannot catch all problems though: see Field::set_warning(), in
which a call to push_warning_printf() has a variable error
(thus, not replacable by a string literal); I checked set_warning() calls
by hand though.
See also WL 5883 for one proposal to avoid such bugs from appearing
again in the future.
The issues fixed in the patch are:
a) mismatch in types (like 'int' passed to '%ld')
b) more arguments passed than specified in the format.
This patch resolves mismatches by changing the type/number of arguments,
not by changing error messages of sql/share/errmsg.txt. The latter would be wrong,
per the following old rule: errmsg.txt must be as stable as possible; no insertions
or deletions of messages, no changes of type or number of printf-like format specifiers,
are allowed, as long as the change impacts a message already released in a GA version.
If this rule is not followed:
- Connectors, which use error message numbers, will be confused (by insertions/deletions
of messages)
- using errmsg.sys of MySQL 5.1.n with mysqld of MySQL 5.1.(n+1)
could produce wrong messages or crash; such usage can easily happen if
installing 5.1.(n+1) while /etc/my.cnf still has --language=/path/to/5.1.n/xxx;
or if copying mysqld from 5.1.(n+1) into a 5.1.n installation.
When fixing b), I have verified that the superfluous arguments were not used in the format
in the first 5.1 GA (5.1.30 'bteam@astra04-20081114162938-z8mctjp6st27uobm').
Had they been used, then passing them today, even if the message doesn't use them
anymore, would have been necessary, as explained above.
2011-05-16 22:04:01 +02:00
|
|
|
typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...)
|
|
|
|
ATTRIBUTE_FORMAT_FPTR(printf, 2, 3);
|
|
|
|
|
2010-06-10 17:16:43 -03:00
|
|
|
/**
|
|
|
|
Used to retrieve a reference to the object (variable) that holds the value
|
|
|
|
for the given option. For example, if var_type is GET_UINT, the function
|
|
|
|
must return a pointer to a variable of type uint. A argument is stored in
|
|
|
|
the location pointed to by the returned pointer.
|
|
|
|
*/
|
|
|
|
typedef void *(*my_getopt_value)(const char *, uint, const struct my_option *,
|
|
|
|
int *);
|
2004-08-14 03:38:37 +02:00
|
|
|
|
2004-08-31 21:27:58 +05:00
|
|
|
extern char *disabled_my_option;
|
|
|
|
extern my_bool my_getopt_print_errors;
|
2007-03-02 08:43:45 -08:00
|
|
|
extern my_bool my_getopt_skip_unknown;
|
2004-08-31 21:27:58 +05:00
|
|
|
extern my_error_reporter my_getopt_error_reporter;
|
|
|
|
|
2002-01-31 04:36:58 +02:00
|
|
|
extern int handle_options (int *argc, char ***argv,
|
2004-08-31 21:27:58 +05:00
|
|
|
const struct my_option *longopts, my_get_one_option);
|
2007-10-04 10:55:08 -07:00
|
|
|
extern void my_cleanup_options(const struct my_option *options);
|
2002-02-06 17:22:43 +02:00
|
|
|
extern void my_print_help(const struct my_option *options);
|
|
|
|
extern void my_print_variables(const struct my_option *options);
|
2010-06-10 17:16:43 -03:00
|
|
|
extern void my_getopt_register_get_addr(my_getopt_value);
|
2002-04-02 20:29:53 +03:00
|
|
|
|
2007-11-30 06:32:04 +01:00
|
|
|
ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
|
2008-02-18 23:29:39 +01:00
|
|
|
my_bool *fix);
|
|
|
|
longlong getopt_ll_limit_value(longlong, const struct my_option *,
|
|
|
|
my_bool *fix);
|
2002-07-23 18:31:22 +03:00
|
|
|
my_bool getopt_compare_strings(const char *s, const char *t, uint length);
|
2004-08-18 22:31:01 +02:00
|
|
|
|
2002-04-02 20:29:53 +03:00
|
|
|
C_MODE_END
|
2004-08-18 22:31:01 +02:00
|
|
|
|
|
|
|
#endif /* _my_getopt_h */
|
|
|
|
|