Commit 3e569727 authored by Sergei Golubchik's avatar Sergei Golubchik

cleanup: unify --defaults* option handling

process all --defaults* options uniformly,
get rid of special case for --no-defaults and --print-defaults
use realpath instead of blindly concatenating pwd and relative path.
parent 3ea51b51
...@@ -146,16 +146,14 @@ int main(int argc, char **argv) ...@@ -146,16 +146,14 @@ int main(int argc, char **argv)
int count, error, args_used; int count, error, args_used;
char **load_default_groups= 0, *tmp_arguments[6]; char **load_default_groups= 0, *tmp_arguments[6];
char **argument, **arguments, **org_argv; char **argument, **arguments, **org_argv;
char *defaults, *extra_defaults, *group_suffix;
int nargs, i= 0; int nargs, i= 0;
MY_INIT(argv[0]); MY_INIT(argv[0]);
org_argv= argv; org_argv= argv;
args_used= get_defaults_options(argc, argv, &defaults, &extra_defaults, args_used= get_defaults_options(argv);
&group_suffix);
/* Copy defaults-xxx arguments & program name */ /* Copy defaults-xxx arguments & program name */
count=args_used+1; count=args_used;
arguments= tmp_arguments; arguments= tmp_arguments;
memcpy((char*) arguments, (char*) org_argv, count * sizeof(*org_argv)); memcpy((char*) arguments, (char*) org_argv, count * sizeof(*org_argv));
arguments[count]= 0; arguments[count]= 0;
......
...@@ -26,9 +26,7 @@ extern const char *my_defaults_file; ...@@ -26,9 +26,7 @@ extern const char *my_defaults_file;
extern my_bool my_getopt_use_args_separator; extern my_bool my_getopt_use_args_separator;
extern my_bool my_getopt_is_args_separator(const char* arg); extern my_bool my_getopt_is_args_separator(const char* arg);
extern int get_defaults_options(int argc, char **argv, extern int get_defaults_options(char **argv);
char **defaults, char **extra_defaults,
char **group_suffix);
extern int my_load_defaults(const char *conf_file, const char **groups, extern int my_load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv, const char ***); int *argc, char ***argv, const char ***);
extern int load_defaults(const char *conf_file, const char **groups, extern int load_defaults(const char *conf_file, const char **groups,
......
...@@ -2,11 +2,11 @@ Could not open required defaults file: /path/with/no/extension ...@@ -2,11 +2,11 @@ Could not open required defaults file: /path/with/no/extension
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
Could not open required defaults file: /path/with.ext Could not open required defaults file: /path/with.ext
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
Could not open required defaults file: MYSQL_TEST_DIR/relative/path/with.ext Could not open required defaults file: relative/path/with.ext
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
Could not open required defaults file: MYSQL_TEST_DIR/relative/path/without/extension Could not open required defaults file: relative/path/without/extension
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
Could not open required defaults file: MYSQL_TEST_DIR/with.ext Could not open required defaults file: with.ext
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
Could not open required defaults file: MYSQL_TEST_DIR/no_extension Could not open required defaults file: no_extension
Fatal error in defaults handling. Program aborted Fatal error in defaults handling. Program aborted
...@@ -13,19 +13,15 @@ exec $MYSQLD --defaults-file=/path/with/no/extension --print-defaults 2>&1; ...@@ -13,19 +13,15 @@ exec $MYSQLD --defaults-file=/path/with/no/extension --print-defaults 2>&1;
--error 1 --error 1
exec $MYSQLD --defaults-file=/path/with.ext --print-defaults 2>&1; exec $MYSQLD --defaults-file=/path/with.ext --print-defaults 2>&1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--error 1 --error 1
exec $MYSQLD --defaults-file=relative/path/with.ext --print-defaults 2>&1; exec $MYSQLD --defaults-file=relative/path/with.ext --print-defaults 2>&1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--error 1 --error 1
exec $MYSQLD --defaults-file=relative/path/without/extension --print-defaults 2>&1; exec $MYSQLD --defaults-file=relative/path/without/extension --print-defaults 2>&1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--error 1 --error 1
exec $MYSQLD --defaults-file=with.ext --print-defaults 2>&1; exec $MYSQLD --defaults-file=with.ext --print-defaults 2>&1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--error 1 --error 1
exec $MYSQLD --defaults-file=no_extension --print-defaults 2>&1; exec $MYSQLD --defaults-file=no_extension --print-defaults 2>&1;
...@@ -69,26 +69,19 @@ ...@@ -69,26 +69,19 @@
See BUG#25192 See BUG#25192
*/ */
static const char *args_separator= "----args-separator----";
inline static void set_args_separator(char** arg) static char *args_separator= (char*)"----args-separator----";
{
DBUG_ASSERT(my_getopt_use_args_separator);
*arg= (char*)args_separator;
}
my_bool my_getopt_use_args_separator= FALSE; my_bool my_getopt_use_args_separator= FALSE;
my_bool my_getopt_is_args_separator(const char* arg) my_bool my_getopt_is_args_separator(const char* arg)
{ {
return (arg == args_separator); return (arg == args_separator);
} }
my_bool my_no_defaults=FALSE, my_print_defaults= FALSE;
const char *my_defaults_file=0; const char *my_defaults_file=0;
const char *my_defaults_group_suffix=0; const char *my_defaults_group_suffix=0;
const char *my_defaults_extra_file=0; const char *my_defaults_extra_file=0;
static char my_defaults_file_buffer[FN_REFLEN];
static char my_defaults_extra_file_buffer[FN_REFLEN];
static my_bool defaults_already_read= FALSE;
/* Which directories are searched for options (and in which order) */ /* Which directories are searched for options (and in which order) */
#define MAX_DEFAULT_DIRS 7 #define MAX_DEFAULT_DIRS 7
...@@ -110,11 +103,11 @@ struct handle_option_ctx ...@@ -110,11 +103,11 @@ struct handle_option_ctx
TYPELIB *group; TYPELIB *group;
}; };
static int search_default_file(struct handle_option_ctx *ctx, static int search_default_file(struct handle_option_ctx *,
const char *dir, const char *config_file); const char *, const char *);
static int search_default_file_with_ext(struct handle_option_ctx *ctx, static int search_default_file_with_ext(struct handle_option_ctx *,
const char *dir, const char *ext, const char *, const char *,
const char *config_file, int recursion_level); const char *, int);
/** /**
...@@ -148,33 +141,6 @@ static const char **init_default_directories(MEM_ROOT *alloc); ...@@ -148,33 +141,6 @@ static const char **init_default_directories(MEM_ROOT *alloc);
static char *remove_end_comment(char *ptr); static char *remove_end_comment(char *ptr);
/*
Expand a file name so that the current working directory is added if
the name is relative.
RETURNS
0 All OK
2 Out of memory or path to long
3 Not able to get working directory
*/
static int
fn_expand(const char *filename, char *result_buf)
{
char dir[FN_REFLEN];
const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH;
DBUG_ENTER("fn_expand");
DBUG_PRINT("enter", ("filename: %s, result_buf: %p",
filename, result_buf));
if (my_getwd(dir, sizeof(dir), MYF(0)))
DBUG_RETURN(3);
DBUG_PRINT("debug", ("dir: %s", dir));
if (fn_format(result_buf, filename, dir, "", flags) == NULL)
DBUG_RETURN(2);
DBUG_PRINT("return", ("result: %s", result_buf));
DBUG_RETURN(0);
}
/* /*
Process config files in default directories. Process config files in default directories.
...@@ -184,8 +150,6 @@ fn_expand(const char *filename, char *result_buf) ...@@ -184,8 +150,6 @@ fn_expand(const char *filename, char *result_buf)
If this is a path, then only this file is read. If this is a path, then only this file is read.
argc Pointer to argc of original program argc Pointer to argc of original program
argv Pointer to argv of original program argv Pointer to argv of original program
args_used Pointer to variable for storing the number of
arguments used.
func Pointer to the function to process options func Pointer to the function to process options
func_ctx It's context. Usually it is the structure to func_ctx It's context. Usually it is the structure to
store additional options. store additional options.
...@@ -209,42 +173,14 @@ fn_expand(const char *filename, char *result_buf) ...@@ -209,42 +173,14 @@ fn_expand(const char *filename, char *result_buf)
--defaults_group_suffix --defaults_group_suffix
*/ */
static int my_search_option_files(const char *conf_file, int *argc, static int my_search_option_files(const char *conf_file, int *argc, char ***argv,
char ***argv, uint *args_used,
struct handle_option_ctx *ctx, struct handle_option_ctx *ctx,
const char **default_directories) const char **default_directories)
{ {
const char **dirs, *forced_default_file, *forced_extra_defaults; const char **dirs;
int error= 0; int error= 0;
DBUG_ENTER("my_search_option_files"); DBUG_ENTER("my_search_option_files");
/* Check if we want to force the use a specific default file */
*args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
(char **) &forced_default_file,
(char **) &forced_extra_defaults,
(char **) &my_defaults_group_suffix);
if (! my_defaults_group_suffix)
my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX");
if (forced_extra_defaults && !defaults_already_read)
{
int error= fn_expand(forced_extra_defaults, my_defaults_extra_file_buffer);
if (error)
DBUG_RETURN(error);
my_defaults_extra_file= my_defaults_extra_file_buffer;
}
if (forced_default_file && !defaults_already_read)
{
int error= fn_expand(forced_default_file, my_defaults_file_buffer);
if (error)
DBUG_RETURN(error);
my_defaults_file= my_defaults_file_buffer;
}
defaults_already_read= TRUE;
if (my_defaults_group_suffix) if (my_defaults_group_suffix)
{ {
/* Handle --defaults-group-suffix= */ /* Handle --defaults-group-suffix= */
...@@ -355,50 +291,73 @@ static int add_option(struct handle_option_ctx *ctx, const char *option) ...@@ -355,50 +291,73 @@ static int add_option(struct handle_option_ctx *ctx, const char *option)
SYNOPSIS SYNOPSIS
get_defaults_options() get_defaults_options()
argc Pointer to argc of original program
argv Pointer to argv of original program argv Pointer to argv of original program
defaults --defaults-file option
extra_defaults --defaults-extra-file option DESCRIPTION
Sets my_no_defaults, my_defaults_file, my_defaults_extra_file,
my_defaults_group_suffix, my_print_defaults
RETURN RETURN
# Number of arguments used from *argv # Number of arguments used from *argv
defaults and extra_defaults will be set to option of the appropriate
items of argv array, or to NULL if there are no such options
*/ */
int get_defaults_options(int argc, char **argv, int get_defaults_options(char **argv)
char **defaults,
char **extra_defaults,
char **group_suffix)
{ {
int org_argc= argc; static char file_buffer[FN_REFLEN];
*defaults= *extra_defaults= *group_suffix= 0; static char extra_file_buffer[FN_REFLEN];
char **orig_argv= argv;
while (argc >= 2) argv++; /* Skip program name */
my_defaults_file= my_defaults_group_suffix= my_defaults_extra_file= 0;
my_no_defaults= my_print_defaults= FALSE;
if (*argv && !strcmp(*argv, "--no-defaults"))
{ {
/* Skip program name or previously handled argument */ my_no_defaults= 1;
argv++; argv++;
if (!*defaults && is_prefix(*argv,"--defaults-file=")) }
else
for(; *argv; argv++)
{ {
*defaults= *argv + sizeof("--defaults-file=")-1; if (!my_defaults_file && is_prefix(*argv, "--defaults-file="))
argc--; my_defaults_file= *argv + sizeof("--defaults-file=")-1;
continue; else
if (!my_defaults_extra_file && is_prefix(*argv, "--defaults-extra-file="))
my_defaults_extra_file= *argv + sizeof("--defaults-extra-file=")-1;
else
if (!my_defaults_group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
my_defaults_group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
else
break;
} }
if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
if (*argv && !strcmp(*argv, "--print-defaults"))
{ {
*extra_defaults= *argv + sizeof("--defaults-extra-file=")-1; my_print_defaults= 1;
argc--; argv++;
continue;
} }
if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
if (! my_defaults_group_suffix)
my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX");
if (my_defaults_extra_file && my_defaults_extra_file != extra_file_buffer)
{ {
*group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; int error= my_realpath(extra_file_buffer, my_defaults_extra_file, MYF(0));
argc--; if (error)
continue; return error;
my_defaults_extra_file= extra_file_buffer;
} }
break;
if (my_defaults_file && my_defaults_file != file_buffer)
{
int error= my_realpath(file_buffer, my_defaults_file, MYF(0));
if (error)
return error;
my_defaults_file= file_buffer;
} }
return org_argc - argc;
return (int)(argv - orig_argv);
} }
/* /*
...@@ -469,55 +428,31 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc, ...@@ -469,55 +428,31 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc,
char ***argv, const char ***default_directories) char ***argv, const char ***default_directories)
{ {
DYNAMIC_ARRAY args; DYNAMIC_ARRAY args;
TYPELIB group; int args_used= 0;
my_bool found_print_defaults= 0;
uint args_used= 0;
int error= 0; int error= 0;
MEM_ROOT alloc; MEM_ROOT alloc;
char *ptr,**res; char *ptr,**res;
struct handle_option_ctx ctx;
const char **dirs; const char **dirs;
uint args_sep= my_getopt_use_args_separator ? 1 : 0; DBUG_ENTER("my_load_defaults");
DBUG_ENTER("load_defaults");
init_alloc_root(&alloc, "my_load_defaults", 512, 0, MYF(0)); init_alloc_root(&alloc, "my_load_defaults", 512, 0, MYF(0));
if ((dirs= init_default_directories(&alloc)) == NULL) if ((dirs= init_default_directories(&alloc)) == NULL)
goto err; goto err;
/*
Check if the user doesn't want any default option processing args_used= get_defaults_options(*argv);
--no-defaults is always the first option
*/ if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0)))
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
/* remove the --no-defaults argument and return only the other arguments */
uint i, j;
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(*argc + 1)*sizeof(char*))))
goto err; goto err;
res= (char**) (ptr+sizeof(alloc));
res[0]= **argv; /* Copy program name */ insert_dynamic(&args, *argv);/* Name MUST be set, even by embedded library */
j= 1; /* Start from 1 for the reset result args */
if (my_getopt_use_args_separator) *argc-= args_used;
*argv+= args_used;
if (!my_no_defaults)
{ {
/* set arguments separator */ TYPELIB group; // XXX
set_args_separator(&res[1]); struct handle_option_ctx ctx;
j++;
}
for (i=2 ; i < (uint) *argc ; i++, j++)
res[j]=argv[0][i];
res[j]=0; /* End pointer */
/*
Update the argc, if have not added args separator, then we have
to decrease argc because we have removed the "--no-defaults".
*/
if (!my_getopt_use_args_separator)
(*argc)--;
*argv=res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
if (default_directories)
*default_directories= dirs;
DBUG_RETURN(0);
}
group.count=0; group.count=0;
group.name= "defaults"; group.name= "defaults";
...@@ -526,63 +461,39 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc, ...@@ -526,63 +461,39 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc,
for (; *groups ; groups++) for (; *groups ; groups++)
group.count++; group.count++;
if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0)))
goto err;
ctx.alloc= &alloc; ctx.alloc= &alloc;
ctx.args= &args; ctx.args= &args;
ctx.group= &group; ctx.group= &group;
if ((error= my_search_option_files(conf_file, argc, argv, &args_used, &ctx, if ((error= my_search_option_files(conf_file, argc - args_used,
dirs))) argv + args_used, &ctx, dirs)))
{ {
delete_dynamic(&args); delete_dynamic(&args);
free_root(&alloc,MYF(0)); free_root(&alloc,MYF(0));
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/* }
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file if (!(ptr=(char*) alloc_root(&alloc, sizeof(alloc) +
*/ (args.elements + *argc + 3) * sizeof(char*))))
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(args.elements + *argc + 1 + args_sep) *sizeof(char*))))
goto err; goto err;
res= (char**) (ptr+sizeof(alloc)); res= (char**) (ptr+sizeof(alloc));
/* copy name + found arguments + command line arguments to new array */ /* found arguments + command line arguments to new array */
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */ memcpy(res, args.buffer, args.elements * sizeof(char*));
memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*));
/* Skip --defaults-xxx options */
(*argc)-= args_used;
(*argv)+= args_used;
/*
Check if we want to see the new argument list
This options must always be the last of the default options
*/
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
{
found_print_defaults=1;
--*argc; ++*argv; /* skip argument */
}
if (my_getopt_use_args_separator) if (my_getopt_use_args_separator)
{ res[args.elements++]= args_separator;
/* set arguments separator for arguments from config file and
command line */
set_args_separator(&res[args.elements+1]);
}
if (*argc) if (*argc)
memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1), memcpy(res + args.elements, *argv, *argc * sizeof(char*));
(*argc-1)*sizeof(char*));
res[args.elements+ *argc+args_sep]=0; /* last null */
(*argc)+=args.elements+args_sep; (*argc)+= args.elements;
*argv= (char**) res; *argv= res;
(*argv)[*argc]= 0;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
delete_dynamic(&args); delete_dynamic(&args);
if (found_print_defaults) if (my_print_defaults)
{ {
int i; int i;
printf("%s would have been started with the following arguments:\n", printf("%s would have been started with the following arguments:\n",
...@@ -718,7 +629,7 @@ static int search_default_file_with_ext(struct handle_option_ctx *ctx, ...@@ -718,7 +629,7 @@ static int search_default_file_with_ext(struct handle_option_ctx *ctx,
MY_DIR *search_dir; MY_DIR *search_dir;
FILEINFO *search_file; FILEINFO *search_file;
if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3) if (safe_strlen(dir) + strlen(config_file) >= FN_REFLEN-3)
return 0; /* Ignore wrong paths */ return 0; /* Ignore wrong paths */
if (dir) if (dir)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment