Commit ad077b8d authored by unknown's avatar unknown

Merge work.mysql.com:/home/bk/mysql

into tetra.spaceapes.com:/usr/home/jcole/bk/mysql


sql/mysqld.cc:
  Auto merged
parents 4c675c92 0cd425bf
...@@ -13,5 +13,6 @@ if test -d /usr/local/BerkeleyDB-dbug/ ...@@ -13,5 +13,6 @@ if test -d /usr/local/BerkeleyDB-dbug/
then then
extra_configs="$extra_configs --with-berkeley-db=/usr/local/BerkeleyDB-dbug/" extra_configs="$extra_configs --with-berkeley-db=/usr/local/BerkeleyDB-dbug/"
fi fi
extra_configs="$extra_configs --with-innobase"
. "$path/FINISH.sh" . "$path/FINISH.sh"
...@@ -1245,7 +1245,7 @@ owns the copyright to the @strong{MySQL} server source code and the ...@@ -1245,7 +1245,7 @@ owns the copyright to the @strong{MySQL} server source code and the
@strong{MySQL} trademark. A significant amount of revenues from our @strong{MySQL} trademark. A significant amount of revenues from our
services goes to developing @strong{MySQL}. @xref{What-is}. services goes to developing @strong{MySQL}. @xref{What-is}.
@strong{MySQL AB} has been profitable providing MySQL AB from the start. @strong{MySQL AB} has been profitable providing @strong{MySQL AB} from the start.
We don't get any outside funding, but have earned all our money ourselves. We don't get any outside funding, but have earned all our money ourselves.
We are searching after partners that would like to support our We are searching after partners that would like to support our
...@@ -1280,7 +1280,7 @@ under a normal commercial copyright. If you are interested in this you can ...@@ -1280,7 +1280,7 @@ under a normal commercial copyright. If you are interested in this you can
buy @strong{MySQL} licenses at @uref{https://order.mysql.com/} or contact buy @strong{MySQL} licenses at @uref{https://order.mysql.com/} or contact
us at @email{licensing@@mysql.com}. us at @email{licensing@@mysql.com}.
@item @item
Advertising; @uref{http://www.mysql.com} is a very popular web site with Advertising; @uref{http://www.mysql.com/} is a very popular web site with
more than 10,000,000 page views per months (January 2001). By putting a more than 10,000,000 page views per months (January 2001). By putting a
banner on this you are guaranteed to reach a lot of potential customers banner on this you are guaranteed to reach a lot of potential customers
in the Open source, Linux and database community. If you are interested in the Open source, Linux and database community. If you are interested
...@@ -1289,7 +1289,7 @@ in this email @email{advertising@@mysql.com}. ...@@ -1289,7 +1289,7 @@ in this email @email{advertising@@mysql.com}.
We are building a partner program to be able to provide @strong{MySQL} We are building a partner program to be able to provide @strong{MySQL}
services in every country. If you are interested in becomming a partner services in every country. If you are interested in becomming a partner
of @strong{MySQL AB} please visit of @strong{MySQL AB} please visit
@uref{http://ww.mysql.com/information/partners.html} or email @uref{http://www.mysql.com/information/partners.html} or email
@email{partner@@mysql.com}. @email{partner@@mysql.com}.
@item @item
We provide @strong{MySQL} training through our partner programs. For more We provide @strong{MySQL} training through our partner programs. For more
...@@ -8567,36 +8567,39 @@ and change privileges with @code{GRANT} and @code{REVOKE} commands. ...@@ -8567,36 +8567,39 @@ and change privileges with @code{GRANT} and @code{REVOKE} commands.
@subsection Connecting to a Remote MySQL from Windows with SSH @subsection Connecting to a Remote MySQL from Windows with SSH
Here is a note about how to connect to get a secure connection to remote MySQL Here is a note about how to connect to get a secure connection to remote MySQL
server with SSH (by David Carlson): server with SSH (by David Carlson @email{dcarlson@@mplcomm.com}):
@itemize @bullet @itemize @bullet
@item @item
Install SSH client on your windows machine - I used a free SSH client Install an SSH client on your windows machine - As a user, the best non-free
from @uref{http://www.doc.ic.ac.uk/~ci2/ssh/}. one I've found is from @code{secureCRT} from @uref{http://www.vandyke.com/}.
Other useful links: Another option is @code{f-secure} from @uref{http://www.f-secure.com/}. You
@uref{http://www.npaci.edu/Security/npaci_security_software.html} and can also find some free ones on @strong{Google} at
@uref{http://www.npaci.edu/Security/samples/ssh32_windows/index.html}. @uref{http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cryptography/SSH/Clients/Windows/}.
@item @item
Start SSH. Set Host Name = yourmysqlserver name or IP address. Set Start your windows SSH client. Set @code{Host_Name = yourmysqlserver_URL_or_IP}. Set
userid=your userid to log in to your server. @code{userid=your_userid} to log in to your server (probably not the same as your @strong{MySQL} login/ password.
@item @item
Click on "local forwards". Set @code{local port: 3306}, Set up port forwarding. Either do a remote forward (Set @code{local_port: 3306}, @code{remote_host: yourmysqlservername_or_ip}, @code{remote_port: 3306} )
@code{host: localhost}, @code{remote port: 3306}. or a local forward (Set @code{port: 3306}, @code{host: localhost}, @code{remote port: 3306}).
@item @item
Save everything, otherwise you'll have to redo it the next time. Save everything, otherwise you'll have to redo it the next time.
@item @item
Log in to your server with SSH. Log in to your server with SSH session you just created.
@item @item
Start some ODBC application (for example Access). Start some ODBC application on your windows machine (for example Access).
@item @item
Create a new file and link to mySQL using the ODBC driver the same way Create a new file in windows and link to @strong{MySQL} using the ODBC driver the same way
you normally do except for server, user "localhost". you normally do, EXCEPT type in @code{localhost} for the @strong{MySQL} host server - not @code{yourmysqlservername}.
@end itemize @end itemize
That's it. It works very well with a direct Internet connection. I'm You should now have your ODBC connection to @strong{MySQL} encrypted using SSH.
having problems with SSH conflicting with my Win95 network and Wingate -
but that'll be the topic of a posting on another software company's
usegroup!
@cindex symbolic links @cindex symbolic links
@cindex using multiple disks to start data @cindex using multiple disks to start data
...@@ -9576,6 +9579,7 @@ uses: ...@@ -9576,6 +9579,7 @@ uses:
@findex command-line options @findex command-line options
@cindex options, command-line @cindex options, command-line
@cindex mysqld options
@node Command-line options, Option files, Automatic start, Post-installation @node Command-line options, Option files, Automatic start, Post-installation
@subsection Command-line Options @subsection Command-line Options
...@@ -11519,6 +11523,11 @@ in the grant tables. In principle, the @code{--secure} option to ...@@ -11519,6 +11523,11 @@ in the grant tables. In principle, the @code{--secure} option to
@code{mysqld} should make hostnames safe. In any case, you should be very @code{mysqld} should make hostnames safe. In any case, you should be very
careful about creating grant table entries using hostname values that careful about creating grant table entries using hostname values that
contain wild cards! contain wild cards!
@item
If you want to restrict the number of connections for a single user, you
can do this by setting the @code{max_user_connections} variable in
@code{mysqld}.
@end itemize @end itemize
@node Privileges options, What Privileges, Security, Privilege system @node Privileges options, What Privileges, Security, Privilege system
...@@ -21045,6 +21054,9 @@ The number of bytes to use when sorting @code{BLOB} or @code{TEXT} ...@@ -21045,6 +21054,9 @@ The number of bytes to use when sorting @code{BLOB} or @code{TEXT}
values (only the first @code{max_sort_length} bytes of each value values (only the first @code{max_sort_length} bytes of each value
are used; the rest are ignored). are used; the rest are ignored).
@item @code{max_user_connections}
The maximum number of active connections for a single user (0 = no limit).
@item @code{max_tmp_tables} @item @code{max_tmp_tables}
(This option doesn't yet do anything.) (This option doesn't yet do anything.)
Maximum number of temporary tables a client can keep open at the same time. Maximum number of temporary tables a client can keep open at the same time.
...@@ -41582,6 +41594,11 @@ not yet 100 % confident in this code. ...@@ -41582,6 +41594,11 @@ not yet 100 % confident in this code.
@appendixsubsec Changes in release 3.23.34 @appendixsubsec Changes in release 3.23.34
@itemize @bullet @itemize @bullet
@item @item
Added option @code{max_user_connections} to @code{mysqld}.
@item
Limit query length for replication by max_allowed_packet, not the arbitrary
limit of 4 MB
@item
Allow space around @code{=} in argument to @code{--set-variable}. Allow space around @code{=} in argument to @code{--set-variable}.
@item @item
Fixed problem in automatic repair that could let some threads in state Fixed problem in automatic repair that could let some threads in state
...@@ -41603,7 +41620,7 @@ Fixed that @code{mysqlbinlog} writes the timestamp value for each query. ...@@ -41603,7 +41620,7 @@ Fixed that @code{mysqlbinlog} writes the timestamp value for each query.
This ensures that on gets same values for date functions like @code{NOW()} This ensures that on gets same values for date functions like @code{NOW()}
when using @code{mysqlbinlog} to pipe the queries to another server. when using @code{mysqlbinlog} to pipe the queries to another server.
@item @item
Allow one to use @code{--skip-gemeni}, @code{--skip-bdb} and Allow one to use @code{--skip-gemini}, @code{--skip-bdb} and
@code{--skip-innobase} to @code{mysqld} even if these databases are not @code{--skip-innobase} to @code{mysqld} even if these databases are not
compiled in @code{mysqld}. compiled in @code{mysqld}.
@item @item
...@@ -203,4 +203,5 @@ ...@@ -203,4 +203,5 @@
#define ER_BAD_SLAVE 1200 #define ER_BAD_SLAVE 1200
#define ER_MASTER_INFO 1201 #define ER_MASTER_INFO 1201
#define ER_SLAVE_THREAD 1202 #define ER_SLAVE_THREAD 1202
#define ER_ERROR_MESSAGES 203 #define ER_TOO_MANY_USER_CONNECTIONS 1203
#define ER_ERROR_MESSAGES 204
# Process this file with autoconf to produce a configure script # Process this file with autoconf to produce a configure script
AC_INIT(./os/os0file.c) AC_INIT
AM_MAINTAINER_MODE
AM_CONFIG_HEADER(ib_config.h) AM_CONFIG_HEADER(ib_config.h)
AM_INIT_AUTOMAKE(ib, 0.90) AM_INIT_AUTOMAKE(ib, 0.90)
AC_PROG_CC AC_PROG_CC
......
...@@ -9,6 +9,7 @@ Created 5/7/1996 Heikki Tuuri ...@@ -9,6 +9,7 @@ Created 5/7/1996 Heikki Tuuri
#ifndef lock0types_h #ifndef lock0types_h
#define lock0types_h #define lock0types_h
#define lock_t ib_lock_t
typedef struct lock_struct lock_t; typedef struct lock_struct lock_t;
typedef struct lock_sys_struct lock_sys_t; typedef struct lock_sys_struct lock_sys_t;
......
...@@ -25,8 +25,8 @@ struct os_event_struct { ...@@ -25,8 +25,8 @@ struct os_event_struct {
fields */ fields */
ibool is_set; /* this is TRUE if the next mutex is ibool is_set; /* this is TRUE if the next mutex is
not reserved */ not reserved */
os_fast_mutex_t wait_mutex; /* this mutex is used in waiting for pthread_cond_t cond_var; /* condition variable is used in
the event */ waiting for the event */
}; };
typedef struct os_event_struct os_event_struct_t; typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t; typedef os_event_struct_t* os_event_t;
...@@ -190,9 +190,9 @@ os_fast_mutex_free( ...@@ -190,9 +190,9 @@ os_fast_mutex_free(
/*===============*/ /*===============*/
os_fast_mutex_t* fast_mutex); /* in: mutex to free */ os_fast_mutex_t* fast_mutex); /* in: mutex to free */
#endif #endif
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "os0sync.ic" #include "os0sync.ic"
#endif #endif
#endif #endif
...@@ -9,6 +9,7 @@ Created 9/5/1995 Heikki Tuuri ...@@ -9,6 +9,7 @@ Created 9/5/1995 Heikki Tuuri
#ifndef sync0types_h #ifndef sync0types_h
#define sync0types_h #define sync0types_h
#define mutex_t ib_mutex_t
typedef struct mutex_struct mutex_t; typedef struct mutex_struct mutex_t;
......
...@@ -316,8 +316,11 @@ os_file_create( ...@@ -316,8 +316,11 @@ os_file_create(
UT_NOT_USED(purpose); UT_NOT_USED(purpose);
if (create_mode == OS_FILE_CREATE) { if (create_mode == OS_FILE_CREATE) {
#ifndef S_IRWXU
file = open(name, create_flag);
#else
file = open(name, create_flag, S_IRWXU | S_IRWXG | S_IRWXO); file = open(name, create_flag, S_IRWXU | S_IRWXG | S_IRWXO);
#endif
} else { } else {
file = open(name, create_flag); file = open(name, create_flag);
} }
......
...@@ -19,14 +19,14 @@ Created 9/6/1995 Heikki Tuuri ...@@ -19,14 +19,14 @@ Created 9/6/1995 Heikki Tuuri
#include "ut0mem.h" #include "ut0mem.h"
/* Type definition for an operating system mutex struct */ /* Type definition for an operating system mutex struct */
struct os_mutex_struct{ struct os_mutex_struct{
void* handle; /* OS handle to mutex */ void* handle; /* OS handle to mutex */
ulint count; /* we use this counter to check ulint count; /* we use this counter to check
that the same thread does not that the same thread does not
recursively lock the mutex: we recursively lock the mutex: we
do not assume that the OS mutex do not assume that the OS mutex
supports recursive locking, though supports recursive locking, though
NT seems to do that */ NT seems to do that */
}; };
/************************************************************* /*************************************************************
...@@ -44,7 +44,7 @@ os_event_create( ...@@ -44,7 +44,7 @@ os_event_create(
{ {
#ifdef __WIN__ #ifdef __WIN__
HANDLE event; HANDLE event;
event = CreateEvent(NULL, /* No security attributes */ event = CreateEvent(NULL, /* No security attributes */
TRUE, /* Manual reset */ TRUE, /* Manual reset */
FALSE, /* Initial state nonsignaled */ FALSE, /* Initial state nonsignaled */
...@@ -60,9 +60,9 @@ os_event_create( ...@@ -60,9 +60,9 @@ os_event_create(
event = ut_malloc(sizeof(struct os_event_struct)); event = ut_malloc(sizeof(struct os_event_struct));
os_fast_mutex_init(&(event->os_mutex)); os_fast_mutex_init(&(event->os_mutex));
os_fast_mutex_init(&(event->wait_mutex)); pthread_cond_init(&(event->cond_var), NULL);
event->is_set = TRUE; event->is_set = FALSE;
return(event); return(event);
#endif #endif
...@@ -108,7 +108,7 @@ os_event_set( ...@@ -108,7 +108,7 @@ os_event_set(
/*=========*/ /*=========*/
os_event_t event) /* in: event to set */ os_event_t event) /* in: event to set */
{ {
#ifdef __WIN__ #ifdef __WIN__
ut_a(event); ut_a(event);
ut_a(SetEvent(event)); ut_a(SetEvent(event));
#else #else
...@@ -119,12 +119,12 @@ os_event_set( ...@@ -119,12 +119,12 @@ os_event_set(
if (event->is_set) { if (event->is_set) {
/* Do nothing */ /* Do nothing */
} else { } else {
os_fast_mutex_unlock(&(event->wait_mutex));
event->is_set = TRUE; event->is_set = TRUE;
pthread_cond_broadcast(&(event->cond_var));
} }
os_fast_mutex_unlock(&(event->os_mutex)); os_fast_mutex_unlock(&(event->os_mutex));
#endif #endif
} }
/************************************************************** /**************************************************************
...@@ -148,7 +148,6 @@ os_event_reset( ...@@ -148,7 +148,6 @@ os_event_reset(
if (!event->is_set) { if (!event->is_set) {
/* Do nothing */ /* Do nothing */
} else { } else {
os_fast_mutex_lock(&(event->wait_mutex));
event->is_set = FALSE; event->is_set = FALSE;
} }
...@@ -163,7 +162,7 @@ void ...@@ -163,7 +162,7 @@ void
os_event_free( os_event_free(
/*==========*/ /*==========*/
os_event_t event) /* in: event to free */ os_event_t event) /* in: event to free */
{ {
#ifdef __WIN__ #ifdef __WIN__
ut_a(event); ut_a(event);
...@@ -173,7 +172,7 @@ os_event_free( ...@@ -173,7 +172,7 @@ os_event_free(
ut_a(event); ut_a(event);
os_fast_mutex_free(&(event->os_mutex)); os_fast_mutex_free(&(event->os_mutex));
os_fast_mutex_free(&(event->wait_mutex)); pthread_cond_destroy(&(event->cond_var));
ut_free(event); ut_free(event);
#endif #endif
...@@ -197,8 +196,22 @@ os_event_wait( ...@@ -197,8 +196,22 @@ os_event_wait(
ut_a(err == WAIT_OBJECT_0); ut_a(err == WAIT_OBJECT_0);
#else #else
os_fast_mutex_lock(&(event->wait_mutex)); os_fast_mutex_lock(&(event->os_mutex));
os_fast_mutex_unlock(&(event->wait_mutex)); loop:
if (event->is_set == TRUE) {
os_fast_mutex_unlock(&(event->os_mutex));
/* Ok, we may return */
return;
}
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
/* Solaris manual said that spurious wakeups may occur: we have
to check the 'is_set' variable again */
goto loop;
#endif #endif
} }
...@@ -225,7 +238,7 @@ os_event_wait_time( ...@@ -225,7 +238,7 @@ os_event_wait_time(
} else { } else {
err = WaitForSingleObject(event, INFINITE); err = WaitForSingleObject(event, INFINITE);
} }
if (err == WAIT_OBJECT_0) { if (err == WAIT_OBJECT_0) {
return(0); return(0);
...@@ -237,7 +250,7 @@ os_event_wait_time( ...@@ -237,7 +250,7 @@ os_event_wait_time(
} }
#else #else
UT_NOT_USED(time); UT_NOT_USED(time);
/* In Posix this is just an ordinary, infinite wait */ /* In Posix this is just an ordinary, infinite wait */
os_event_wait(event); os_event_wait(event);
...@@ -277,7 +290,7 @@ os_event_wait_multiple( ...@@ -277,7 +290,7 @@ os_event_wait_multiple(
return(index - WAIT_OBJECT_0); return(index - WAIT_OBJECT_0);
#else #else
ut_a(n == 0); ut_a(n == 0);
/* In Posix we can only wait for a single event */ /* In Posix we can only wait for a single event */
os_event_wait(*event_array); os_event_wait(*event_array);
...@@ -318,7 +331,7 @@ os_mutex_create( ...@@ -318,7 +331,7 @@ os_mutex_create(
os_mutex_t mutex_str; os_mutex_t mutex_str;
UT_NOT_USED(name); UT_NOT_USED(name);
os_mutex = ut_malloc(sizeof(os_fast_mutex_t)); os_mutex = ut_malloc(sizeof(os_fast_mutex_t));
os_fast_mutex_init(os_mutex); os_fast_mutex_init(os_mutex);
...@@ -329,7 +342,7 @@ os_mutex_create( ...@@ -329,7 +342,7 @@ os_mutex_create(
mutex_str->count = 0; mutex_str->count = 0;
return(mutex_str); return(mutex_str);
#endif #endif
} }
/************************************************************** /**************************************************************
...@@ -385,7 +398,7 @@ os_mutex_exit( ...@@ -385,7 +398,7 @@ os_mutex_exit(
(mutex->count)--; (mutex->count)--;
os_fast_mutex_unlock(mutex->handle); os_fast_mutex_unlock(mutex->handle);
#endif #endif
} }
/************************************************************** /**************************************************************
...@@ -419,7 +432,7 @@ os_fast_mutex_init( ...@@ -419,7 +432,7 @@ os_fast_mutex_init(
{ {
#ifdef __WIN__ #ifdef __WIN__
ut_a(fast_mutex); ut_a(fast_mutex);
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else #else
pthread_mutex_init(fast_mutex, NULL); pthread_mutex_init(fast_mutex, NULL);
......
...@@ -56,6 +56,9 @@ Created 2/16/1996 Heikki Tuuri ...@@ -56,6 +56,9 @@ Created 2/16/1996 Heikki Tuuri
#include "srv0start.h" #include "srv0start.h"
#include "que0que.h" #include "que0que.h"
ibool srv_is_being_started = FALSE;
ibool srv_was_started = FALSE;
ibool measure_cont = FALSE; ibool measure_cont = FALSE;
os_file_t files[1000]; os_file_t files[1000];
...@@ -443,6 +446,8 @@ innobase_start_or_create_for_mysql(void) ...@@ -443,6 +446,8 @@ innobase_start_or_create_for_mysql(void)
log_do_write = TRUE; log_do_write = TRUE;
/* yydebug = TRUE; */ /* yydebug = TRUE; */
srv_is_being_started = TRUE;
os_aio_use_native_aio = srv_use_native_aio; os_aio_use_native_aio = srv_use_native_aio;
err = srv_boot(); err = srv_boot();
...@@ -676,6 +681,9 @@ innobase_start_or_create_for_mysql(void) ...@@ -676,6 +681,9 @@ innobase_start_or_create_for_mysql(void)
thread_ids + 2 + SRV_MAX_N_IO_THREADS); thread_ids + 2 + SRV_MAX_N_IO_THREADS);
fprintf(stderr, "Innobase: Started\n"); fprintf(stderr, "Innobase: Started\n");
srv_was_started = TRUE;
srv_is_being_started = FALSE;
sync_order_checks_on = TRUE; sync_order_checks_on = TRUE;
/* buf_debug_prints = TRUE; */ /* buf_debug_prints = TRUE; */
...@@ -691,6 +699,14 @@ innobase_shutdown_for_mysql(void) ...@@ -691,6 +699,14 @@ innobase_shutdown_for_mysql(void)
/*=============================*/ /*=============================*/
/* out: DB_SUCCESS or error code */ /* out: DB_SUCCESS or error code */
{ {
if (!srv_was_started) {
if (srv_is_being_started) {
fprintf(stderr,
"Innobase: Warning: shutting down not properly started database\n");
}
return(DB_SUCCESS);
}
/* Flush buffer pool to disk, write the current lsn to /* Flush buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive */ the tablespace header(s), and copy all log data to archive */
......
...@@ -21,5 +21,9 @@ Log_name ...@@ -21,5 +21,9 @@ Log_name
master-bin.003 master-bin.003
master-bin.004 master-bin.004
master-bin.005 master-bin.005
File Position Binlog_do_db Binlog_ignore_db
master-bin.005 1504
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
127.0.0.1 root 9306 60 master-bin.005 1504 Yes 0 0
count(*) count(*)
100 100
...@@ -78,11 +78,13 @@ while ($1) ...@@ -78,11 +78,13 @@ while ($1)
dec $1; dec $1;
} }
show master logs; show master logs;
show master status;
save_master_pos; save_master_pos;
connection slave; connection slave;
slave stop; slave stop;
slave start; slave start;
sync_with_master; sync_with_master;
show slave status;
select count(*) from t3 where n = 4; select count(*) from t3 where n = 4;
#clean up #clean up
connection master; connection master;
......
...@@ -172,9 +172,9 @@ convert_error_code_to_mysql( ...@@ -172,9 +172,9 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW); return(HA_ERR_TO_BIG_ROW);
} else { } else {
assert(0); dbug_assert(0);
return(0); return(-1); // Unknown error
} }
} }
...@@ -194,7 +194,7 @@ check_trx_exists( ...@@ -194,7 +194,7 @@ check_trx_exists(
trx = (trx_t*) thd->transaction.all.innobase_tid; trx = (trx_t*) thd->transaction.all.innobase_tid;
if (trx == NULL) { if (trx == NULL) {
assert(thd != NULL); dbug_assert(thd != NULL);
trx = trx_allocate_for_mysql(); trx = trx_allocate_for_mysql();
thd->transaction.all.innobase_tid = trx; thd->transaction.all.innobase_tid = trx;
...@@ -418,31 +418,41 @@ innobase_init(void) ...@@ -418,31 +418,41 @@ innobase_init(void)
int err; int err;
bool ret; bool ret;
ibool test_bool; ibool test_bool;
static char *current_dir[3];
DBUG_ENTER("innobase_init"); DBUG_ENTER("innobase_init");
test_bool = TRUE; /* Use current_dir if no paths are set */
assert(test_bool == 1); current_dir[0]=FN_CURLIB;
test_bool = FALSE; current_dir[1]=FN_LIBCHAR;
assert(test_bool == 0); current_dir[2]=0;
/* Set Innobase initialization parameters according to the values /* Set Innobase initialization parameters according to the values
read from MySQL .cnf file */ read from MySQL .cnf file */
srv_data_home = innobase_data_home_dir; if (!innobase_data_file_path)
{
fprintf(stderr,"Can't initialize innobase as 'innobase_data_file_path' is not set\n");
DBUG_RETURN(TRUE);
}
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
current_dir);
srv_logs_home = ""; srv_logs_home = "";
srv_arch_dir = innobase_log_arch_dir; srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir :
current_dir);
ret = innobase_parse_data_file_paths_and_sizes(); ret = innobase_parse_data_file_paths_and_sizes();
if (ret == FALSE) { if (ret == FALSE) {
return(TRUE); DBUG_RETURN(TRUE);
} }
if (!innobase_log_group_home_dir)
innobase_log_group_home_dir= current_dir;
ret = innobase_parse_log_group_home_dirs(); ret = innobase_parse_log_group_home_dirs();
if (ret == FALSE) { if (ret == FALSE) {
return(TRUE); DBUG_RETURN(TRUE);
} }
srv_n_log_groups = (ulint) innobase_mirrored_log_groups; srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
...@@ -466,12 +476,12 @@ innobase_init(void) ...@@ -466,12 +476,12 @@ innobase_init(void)
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(1); DBUG_RETURN(1);
} }
(void) hash_init(&innobase_open_tables,32,0,0, (void) hash_init(&innobase_open_tables,32,0,0,
(hash_get_key) innobase_get_key,0,0); (hash_get_key) innobase_get_key,0,0);
pthread_mutex_init(&innobase_mutex,NULL); pthread_mutex_init(&innobase_mutex,NULL);
return(0); DBUG_RETURN(0);
} }
/*********************************************************************** /***********************************************************************
...@@ -490,10 +500,10 @@ innobase_end(void) ...@@ -490,10 +500,10 @@ innobase_end(void)
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(1); DBUG_RETURN(1);
} }
return(0); DBUG_RETURN(0);
} }
/******************************************************************** /********************************************************************
...@@ -666,7 +676,7 @@ normalize_table_name( ...@@ -666,7 +676,7 @@ normalize_table_name(
/* Scan name from the end */ /* Scan name from the end */
ptr = (char*) name + strlen(name) - 1; ptr = strend(name)-1;
while (ptr >= name && *ptr != '\\' && *ptr != '/') { while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--; ptr--;
...@@ -674,7 +684,7 @@ normalize_table_name( ...@@ -674,7 +684,7 @@ normalize_table_name(
name_ptr = ptr + 1; name_ptr = ptr + 1;
assert(ptr > name); dbug_assert(ptr > name);
ptr--; ptr--;
...@@ -770,7 +780,7 @@ ha_innobase::open( ...@@ -770,7 +780,7 @@ ha_innobase::open(
((row_prebuilt_t*)innobase_prebuilt) ((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = TRUE; ->clust_index_was_generated = TRUE;
assert(key_used_on_scan == MAX_KEY); dbug_assert(key_used_on_scan == MAX_KEY);
} }
/* Init table lock structure */ /* Init table lock structure */
...@@ -911,8 +921,8 @@ innobase_mysql_cmp( ...@@ -911,8 +921,8 @@ innobase_mysql_cmp(
{ {
enum_field_types mysql_tp; enum_field_types mysql_tp;
assert(a_length != UNIV_SQL_NULL); dbug_assert(a_length != UNIV_SQL_NULL);
assert(b_length != UNIV_SQL_NULL); dbug_assert(b_length != UNIV_SQL_NULL);
mysql_tp = (enum_field_types) mysql_type; mysql_tp = (enum_field_types) mysql_type;
...@@ -943,11 +953,11 @@ get_innobase_type_from_mysql_type( ...@@ -943,11 +953,11 @@ get_innobase_type_from_mysql_type(
8 bits: this is used in ibuf and also when DATA_NOT_NULL is 8 bits: this is used in ibuf and also when DATA_NOT_NULL is
ORed to the type */ ORed to the type */
assert((ulint)FIELD_TYPE_STRING < 256); dbug_assert((ulint)FIELD_TYPE_STRING < 256);
assert((ulint)FIELD_TYPE_VAR_STRING < 256); dbug_assert((ulint)FIELD_TYPE_VAR_STRING < 256);
assert((ulint)FIELD_TYPE_DOUBLE < 256); dbug_assert((ulint)FIELD_TYPE_DOUBLE < 256);
assert((ulint)FIELD_TYPE_FLOAT < 256); dbug_assert((ulint)FIELD_TYPE_FLOAT < 256);
assert((ulint)FIELD_TYPE_DECIMAL < 256); dbug_assert((ulint)FIELD_TYPE_DECIMAL < 256);
switch (field->type()) { switch (field->type()) {
case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) { case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) {
...@@ -1072,6 +1082,14 @@ build_template( ...@@ -1072,6 +1082,14 @@ build_template(
templ_type = ROW_MYSQL_WHOLE_ROW; templ_type = ROW_MYSQL_WHOLE_ROW;
} }
if (prebuilt->select_lock_type == LOCK_X) {
/* TODO: should fix the code in sql_update so that we could do
with fetching only the needed columns */
templ_type = ROW_MYSQL_WHOLE_ROW;
}
if (templ_type == ROW_MYSQL_REC_FIELDS) { if (templ_type == ROW_MYSQL_REC_FIELDS) {
if (prebuilt->select_lock_type != LOCK_NONE) { if (prebuilt->select_lock_type != LOCK_NONE) {
...@@ -1288,9 +1306,9 @@ calc_row_difference( ...@@ -1288,9 +1306,9 @@ calc_row_difference(
uint n_fields; uint n_fields;
ulint o_len; ulint o_len;
ulint n_len; ulint n_len;
mysql_byte* o_ptr; byte* o_ptr;
mysql_byte* n_ptr; byte* n_ptr;
mysql_byte* buf; byte* buf;
upd_field_t* ufield; upd_field_t* ufield;
ulint col_type; ulint col_type;
ulint is_unsigned; ulint is_unsigned;
...@@ -1300,7 +1318,7 @@ calc_row_difference( ...@@ -1300,7 +1318,7 @@ calc_row_difference(
n_fields = table->fields; n_fields = table->fields;
/* We use upd_buff to convert changed fields */ /* We use upd_buff to convert changed fields */
buf = upd_buff; buf = (byte*) upd_buff;
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
field = table->field[i]; field = table->field[i];
...@@ -1312,8 +1330,8 @@ calc_row_difference( ...@@ -1312,8 +1330,8 @@ calc_row_difference(
goto skip_field; goto skip_field;
} }
o_ptr = old_row + get_field_offset(table, field); o_ptr = (byte*) old_row + get_field_offset(table, field);
n_ptr = new_row + get_field_offset(table, field); n_ptr = (byte*) new_row + get_field_offset(table, field);
o_len = field->pack_length(); o_len = field->pack_length();
n_len = field->pack_length(); n_len = field->pack_length();
...@@ -1353,8 +1371,10 @@ calc_row_difference( ...@@ -1353,8 +1371,10 @@ calc_row_difference(
ufield = uvect->fields + n_changed; ufield = uvect->fields + n_changed;
buf = innobase_convert_and_store_changed_col(ufield, buf = (byte*)
buf, n_ptr, n_len, col_type, innobase_convert_and_store_changed_col(ufield,
(mysql_byte*)buf,
(mysql_byte*)n_ptr, n_len, col_type,
is_unsigned); is_unsigned);
ufield->exp = NULL; ufield->exp = NULL;
ufield->field_no = ufield->field_no =
...@@ -1580,7 +1600,7 @@ ha_innobase::index_read( ...@@ -1580,7 +1600,7 @@ ha_innobase::index_read(
last_match_mode = match_mode; last_match_mode = match_mode;
ret = row_search_for_mysql(buf, mode, prebuilt, match_mode, 0); ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0);
if (ret == DB_SUCCESS) { if (ret == DB_SUCCESS) {
error = 0; error = 0;
...@@ -1690,7 +1710,8 @@ ha_innobase::general_fetch( ...@@ -1690,7 +1710,8 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch"); DBUG_ENTER("general_fetch");
ret = row_search_for_mysql(buf, 0, prebuilt, match_mode, direction); ret = row_search_for_mysql((byte*)buf, 0, prebuilt,
match_mode, direction);
if (ret == DB_SUCCESS) { if (ret == DB_SUCCESS) {
error = 0; error = 0;
...@@ -1935,7 +1956,7 @@ ha_innobase::position( ...@@ -1935,7 +1956,7 @@ ha_innobase::position(
len = store_key_val_for_row(primary_key, (char*) ref, record); len = store_key_val_for_row(primary_key, (char*) ref, record);
} }
assert(len <= ref_length); dbug_assert(len <= ref_length);
ref_stored_len = len; ref_stored_len = len;
} }
...@@ -2174,23 +2195,14 @@ ha_innobase::create( ...@@ -2174,23 +2195,14 @@ ha_innobase::create(
int primary_key_no = -1; int primary_key_no = -1;
KEY* key; KEY* key;
uint i; uint i;
char name2[1000]; char name2[FN_REFLEN];
char norm_name[1000]; char norm_name[FN_REFLEN];
DBUG_ENTER("ha_innobase::create"); DBUG_ENTER("ha_innobase::create");
trx = trx_allocate_for_mysql(); trx = trx_allocate_for_mysql();
name_len = strlen(name); fn_format(name2, name, "", "",2); // Remove the .frm extension
assert(name_len < 1000);
assert(name_len > 4);
memcpy(name2, name, name_len);
/* Erase the .frm end from table name: */
name2[name_len - 4] = '\0';
normalize_table_name(norm_name, name2); normalize_table_name(norm_name, name2);
...@@ -2550,11 +2562,11 @@ ha_innobase::update_table_comment( ...@@ -2550,11 +2562,11 @@ ha_innobase::update_table_comment(
char *str=my_malloc(length + 50,MYF(0)); char *str=my_malloc(length + 50,MYF(0));
if (!str) if (!str)
return comment; return (char*)comment;
sprintf(str,"%s Innobase free: %lu kB", comment,innobase_get_free_space()); sprintf(str,"%s Innobase free: %lu kB", comment,innobase_get_free_space());
return str; return((char*) str);
} }
......
...@@ -85,10 +85,11 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, ...@@ -85,10 +85,11 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO; return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
} }
data_len = uint4korr(buf + EVENT_LEN_OFFSET); data_len = uint4korr(buf + EVENT_LEN_OFFSET);
if (data_len < LOG_EVENT_HEADER_LEN || data_len > MAX_EVENT_LEN) if (data_len < LOG_EVENT_HEADER_LEN || data_len > max_allowed_packet)
{ {
if (log_lock) pthread_mutex_unlock(log_lock); if (log_lock) pthread_mutex_unlock(log_lock);
return LOG_READ_BOGUS; return (data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS :
LOG_READ_TOO_LARGE;
} }
packet->append(buf, sizeof(buf)); packet->append(buf, sizeof(buf));
data_len -= LOG_EVENT_HEADER_LEN; data_len -= LOG_EVENT_HEADER_LEN;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define LOG_READ_IO -3 #define LOG_READ_IO -3
#define LOG_READ_MEM -5 #define LOG_READ_MEM -5
#define LOG_READ_TRUNC -6 #define LOG_READ_TRUNC -6
#define LOG_READ_TOO_LARGE -7
#define LOG_EVENT_OFFSET 4 #define LOG_EVENT_OFFSET 4
#define BINLOG_VERSION 1 #define BINLOG_VERSION 1
...@@ -42,7 +43,6 @@ ...@@ -42,7 +43,6 @@
+ sizeof(uint32) + 2 + sizeof(uint32)) + sizeof(uint32) + 2 + sizeof(uint32))
#define EVENT_LEN_OFFSET 9 #define EVENT_LEN_OFFSET 9
#define EVENT_TYPE_OFFSET 4 #define EVENT_TYPE_OFFSET 4
#define MAX_EVENT_LEN 4*1024*1024
#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN) #define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
#define ROTATE_EVENT_OVERHEAD LOG_EVENT_HEADER_LEN #define ROTATE_EVENT_OVERHEAD LOG_EVENT_HEADER_LEN
#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN+sizeof(sql_ex_info)) #define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN+sizeof(sql_ex_info))
......
...@@ -231,6 +231,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); ...@@ -231,6 +231,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name); bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_init_select(LEX *lex); void mysql_init_select(LEX *lex);
void init_max_user_conn(void);
void free_max_user_conn(void);
pthread_handler_decl(handle_one_connection,arg); pthread_handler_decl(handle_one_connection,arg);
pthread_handler_decl(handle_bootstrap,arg); pthread_handler_decl(handle_bootstrap,arg);
sig_handler end_thread_signal(int sig); sig_handler end_thread_signal(int sig);
...@@ -519,7 +521,7 @@ extern uint protocol_version,dropping_tables; ...@@ -519,7 +521,7 @@ extern uint protocol_version,dropping_tables;
extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size, extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
max_join_size,join_buff_size,tmp_table_size, max_join_size,join_buff_size,tmp_table_size,
max_connections,max_connect_errors,long_query_time, max_connections,max_connect_errors,long_query_time,
max_insert_delayed_threads, max_insert_delayed_threads, max_user_connections,
long_query_count,net_wait_timeout,net_interactive_timeout, long_query_count,net_wait_timeout,net_interactive_timeout,
net_read_timeout,net_write_timeout, net_read_timeout,net_write_timeout,
what_to_log,flush_time, what_to_log,flush_time,
......
...@@ -263,7 +263,7 @@ ulong select_full_range_join_count,select_full_join_count; ...@@ -263,7 +263,7 @@ ulong select_full_range_join_count,select_full_join_count;
ulong specialflag=0,opened_tables=0,created_tmp_tables=0, ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
created_tmp_disk_tables=0; created_tmp_disk_tables=0;
ulong max_connections,max_insert_delayed_threads,max_used_connections, ulong max_connections,max_insert_delayed_threads,max_used_connections,
max_connect_errors; max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid; ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0; ulong slow_launch_threads = 0;
char mysql_real_data_home[FN_REFLEN], char mysql_real_data_home[FN_REFLEN],
...@@ -295,7 +295,8 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count, ...@@ -295,7 +295,8 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_error_log, LOCK_error_log,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_binlog_update, LOCK_slave, LOCK_server_id; LOCK_binlog_update, LOCK_slave, LOCK_server_id,
LOCK_user_conn;
pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update, pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update,
COND_slave_stopped, COND_slave_start; COND_slave_stopped, COND_slave_start;
...@@ -647,6 +648,7 @@ void clean_up(void) ...@@ -647,6 +648,7 @@ void clean_up(void)
my_free(mysql_tmpdir,MYF(0)); my_free(mysql_tmpdir,MYF(0));
x_free(opt_bin_logname); x_free(opt_bin_logname);
bitmap_free(&temp_pool); bitmap_free(&temp_pool);
free_max_user_conn();
#ifndef __WIN__ #ifndef __WIN__
if (!opt_bootstrap) if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
...@@ -1576,6 +1578,7 @@ int main(int argc, char **argv) ...@@ -1576,6 +1578,7 @@ int main(int argc, char **argv)
(void) pthread_mutex_init(&LOCK_binlog_update, NULL); (void) pthread_mutex_init(&LOCK_binlog_update, NULL);
(void) pthread_mutex_init(&LOCK_slave, NULL); (void) pthread_mutex_init(&LOCK_slave, NULL);
(void) pthread_mutex_init(&LOCK_server_id, NULL); (void) pthread_mutex_init(&LOCK_server_id, NULL);
(void) pthread_mutex_init(&LOCK_user_conn, NULL);
(void) pthread_cond_init(&COND_binlog_update, NULL); (void) pthread_cond_init(&COND_binlog_update, NULL);
(void) pthread_cond_init(&COND_slave_stopped, NULL); (void) pthread_cond_init(&COND_slave_stopped, NULL);
(void) pthread_cond_init(&COND_slave_start, NULL); (void) pthread_cond_init(&COND_slave_start, NULL);
...@@ -1766,6 +1769,8 @@ The server will not act as a slave."); ...@@ -1766,6 +1769,8 @@ The server will not act as a slave.");
} }
if (!opt_noacl) if (!opt_noacl)
(void) grant_init(); (void) grant_init();
if (max_user_connections)
init_max_user_conn();
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
if (!opt_noacl) if (!opt_noacl)
...@@ -2631,6 +2636,8 @@ CHANGEABLE_VAR changeable_vars[] = { ...@@ -2631,6 +2636,8 @@ CHANGEABLE_VAR changeable_vars[] = {
1024, 4, 8192*1024L, 0, 1 }, 1024, 4, 8192*1024L, 0, 1 },
{ "max_tmp_tables", (long*) &max_tmp_tables, { "max_tmp_tables", (long*) &max_tmp_tables,
32, 1, ~0L, 0, 1 }, 32, 1, ~0L, 0, 1 },
{ "max_user_connections", (long*) &max_user_connections,
0, 1, ~0L, 0, 1 },
{ "max_write_lock_count", (long*) &max_write_lock_count, { "max_write_lock_count", (long*) &max_write_lock_count,
~0L, 1, ~0L, 0, 1 }, ~0L, 1, ~0L, 0, 1 },
{ "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size, { "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size,
...@@ -2726,6 +2733,7 @@ struct show_var_st init_vars[]= { ...@@ -2726,6 +2733,7 @@ struct show_var_st init_vars[]= {
{"max_heap_table_size", (char*) &max_heap_table_size, SHOW_LONG}, {"max_heap_table_size", (char*) &max_heap_table_size, SHOW_LONG},
{"max_join_size", (char*) &max_join_size, SHOW_LONG}, {"max_join_size", (char*) &max_join_size, SHOW_LONG},
{"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG}, {"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG},
{"max_user_connections", (char*) &max_user_connections, SHOW_LONG},
{"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG}, {"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG},
{"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG}, {"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
...@@ -3849,6 +3857,10 @@ static int get_service_parameters() ...@@ -3849,6 +3857,10 @@ static int get_service_parameters()
{ {
SET_CHANGEABLE_VARVAL( "max_connections" ); SET_CHANGEABLE_VARVAL( "max_connections" );
} }
else if ( lstrcmp(szKeyValueName, TEXT("MaxUserConnections")) == 0 )
{
SET_CHANGEABLE_VARVAL( "max_user_connections" );
}
else if ( lstrcmp(szKeyValueName, TEXT("MaxConnectErrors")) == 0 ) else if ( lstrcmp(szKeyValueName, TEXT("MaxConnectErrors")) == 0 )
{ {
SET_CHANGEABLE_VARVAL( "max_connect_errors" ); SET_CHANGEABLE_VARVAL( "max_connect_errors" );
......
...@@ -213,3 +213,4 @@ ...@@ -213,3 +213,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -207,3 +207,4 @@ ...@@ -207,3 +207,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -208,3 +208,4 @@ ...@@ -208,3 +208,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -207,3 +207,4 @@ ...@@ -207,3 +207,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -206,3 +206,4 @@ ...@@ -206,3 +206,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -206,3 +206,4 @@ ...@@ -206,3 +206,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -206,3 +206,4 @@ ...@@ -206,3 +206,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -206,3 +206,4 @@ ...@@ -206,3 +206,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -208,3 +208,4 @@ ...@@ -208,3 +208,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -204,3 +204,4 @@ ...@@ -204,3 +204,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -208,3 +208,4 @@ ...@@ -208,3 +208,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -207,3 +207,4 @@ ...@@ -207,3 +207,4 @@
" slave, CHANGE MASTER TO", " slave, CHANGE MASTER TO",
" master info, persmissions master.info", " master info, persmissions master.info",
" SLAVE, ", " SLAVE, ",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -212,3 +212,4 @@ ...@@ -212,3 +212,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -205,3 +205,4 @@ ...@@ -205,3 +205,4 @@
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources", "Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
...@@ -199,3 +199,9 @@ ...@@ -199,3 +199,9 @@
"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades",
"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt",
"Denna operation kan inte göras under replikering; Gör SLAVE STOP först",
"Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START",
"Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO",
"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'",
"Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
...@@ -199,8 +199,9 @@ ...@@ -199,8 +199,9 @@
"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades",
"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt",
"This operation cannot be performed with a running slave, run SLAVE STOP first", "Denna operation kan inte göras under replikering; Gör SLAVE STOP först",
"This operation requires a running slave, configure slave and do SLAVE START", "Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info", "Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'",
"Could not create slave thread, check system resources", "Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
...@@ -265,14 +265,14 @@ class THD :public ilink { ...@@ -265,14 +265,14 @@ class THD :public ilink {
pthread_t real_id; pthread_t real_id;
uint current_tablenr,tmp_table,cond_count,col_access,query_length; uint current_tablenr,tmp_table,cond_count,col_access,query_length;
uint server_status,open_options; uint server_status,open_options;
bool slave_thread;
char scramble[9]; char scramble[9];
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error; bool no_errors, allow_sum_func, password, fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used; bool query_start_used,last_insert_id_used,insert_id_used;
bool volatile killed,bootstrap;
bool system_thread,in_lock_tables,global_read_lock; bool system_thread,in_lock_tables,global_read_lock;
bool query_error; bool query_error, bootstrap;
bool volatile killed;
LOG_INFO* current_linfo; LOG_INFO* current_linfo;
// if we do a purge of binary logs, log index info of the threads // if we do a purge of binary logs, log index info of the threads
// that are currently reading it needs to be adjusted. To do that // that are currently reading it needs to be adjusted. To do that
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <thr_alarm.h> #include <thr_alarm.h>
#include <myisam.h> #include <myisam.h>
#include <my_dir.h> #include <my_dir.h>
#include <assert.h>
#define SCRAMBLE_LENGTH 8 #define SCRAMBLE_LENGTH 8
...@@ -32,6 +33,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache; ...@@ -32,6 +33,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
extern "C" int gethostname(char *name, int namelen); extern "C" int gethostname(char *name, int namelen);
#endif #endif
static int check_for_max_user_connections(const char *user, int u_length,
const char *host);
static void decrease_user_connections(const char *user, const char *host);
static bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables); static bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
...@@ -145,13 +149,134 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, ...@@ -145,13 +149,134 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip", thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip",
db ? db : (char*) ""); db ? db : (char*) "");
thd->db_access=0; thd->db_access=0;
if (max_user_connections &&
check_for_max_user_connections(user, strlen(user), thd->host))
return -1;
if (db && db[0]) if (db && db[0])
return test(mysql_change_db(thd,db)); {
bool error=test(mysql_change_db(thd,db));
if (error)
decrease_user_connections(user,thd->host);
return error;
}
else else
send_ok(net); // Ready to handle questions send_ok(net); // Ready to handle questions
return 0; // ok return 0; // ok
} }
/*
** check for maximum allowable user connections
** if mysql server is started with corresponding
** variable that is greater then 0
*/
static HASH hash_user_connections;
static DYNAMIC_ARRAY user_conn_array;
extern pthread_mutex_t LOCK_user_conn;
struct user_conn {
char user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
int connections, len;
};
static byte* get_key_conn(user_conn *buff, uint *length,
my_bool not_used __attribute__((unused)))
{
*length=buff->len;
return (byte*) buff->user;
}
#define DEF_USER_COUNT 50
void init_max_user_conn(void)
{
(void) hash_init(&hash_user_connections,DEF_USER_COUNT,0,0,
(hash_get_key) get_key_conn,0, 0);
(void) init_dynamic_array(&user_conn_array,sizeof(user_conn),
DEF_USER_COUNT, DEF_USER_COUNT);
}
static int check_for_max_user_connections(const char *user, int u_length,
const char *host)
{
uint temp_len;
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
struct user_conn *uc;
if (!user)
user="";
if (!host)
host="";
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
NullS) - temp_user);
(void) pthread_mutex_lock(&LOCK_user_conn);
uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len);
if (uc) /* user found ; check for no. of connections */
{
if (max_user_connections == uc->connections)
{
net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, temp_user);
pthread_mutex_unlock(&LOCK_user_conn);
return 1;
}
uc->connections++;
}
else
{
/* the user is not found in the cache; Insert it */
struct user_conn uc;
memcpy(uc.user,temp_user,temp_len+1);
uc.len = temp_len;
uc.connections = 1;
if (!insert_dynamic(&user_conn_array, (char *) &uc))
{
hash_insert(&hash_user_connections,
(byte *) dynamic_array_ptr(&user_conn_array,
user_conn_array.elements - 1));
}
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
return 0;
}
static void decrease_user_connections(const char *user, const char *host)
{
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
int temp_len;
struct user_conn uucc, *uc;
if (!user)
user="";
if (!host)
host="";
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
NullS) - temp_user);
(void) pthread_mutex_lock(&LOCK_user_conn);
uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len);
dbug_assert(uc != 0); // We should always find the user
if (!uc)
goto end; // Safety; Something went wrong
if (! --uc->connections)
{
/* Last connection for user; Delete it */
(void) hash_delete(&hash_user_connections,(char *) uc);
uint element= ((uint) ((byte*) uc - (byte*) user_conn_array.buffer) /
user_conn_array.size_of_element);
delete_dynamic_element(&user_conn_array,element);
}
end:
(void) pthread_mutex_unlock(&LOCK_user_conn);
}
void free_max_user_conn(void)
{
delete_dynamic(&user_conn_array);
hash_free(&hash_user_connections);
}
/* /*
** check connnetion and get priviliges ** check connnetion and get priviliges
...@@ -417,6 +542,8 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -417,6 +542,8 @@ pthread_handler_decl(handle_one_connection,arg)
thread_safe_increment(aborted_threads,&LOCK_thread_count); thread_safe_increment(aborted_threads,&LOCK_thread_count);
} }
if (max_user_connections)
decrease_user_connections(thd->user,thd->host);
end_thread: end_thread:
close_connection(net); close_connection(net);
end_thread(thd,1); end_thread(thd,1);
...@@ -512,7 +639,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) ...@@ -512,7 +639,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
DBUG_ENTER("mysql_table_dump"); DBUG_ENTER("mysql_table_dump");
db = (db && db[0]) ? db : thd->db; db = (db && db[0]) ? db : thd->db;
if (!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST)))) if (!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory DBUG_RETURN(1); // out of memory
table_list->db = db; table_list->db = db;
table_list->real_name = table_list->name = tbl_name; table_list->real_name = table_list->name = tbl_name;
table_list->lock_type = TL_READ_NO_INSERT; table_list->lock_type = TL_READ_NO_INSERT;
...@@ -641,7 +768,7 @@ bool do_command(THD *thd) ...@@ -641,7 +768,7 @@ bool do_command(THD *thd)
send_error(net, ER_UNKNOWN_COM_ERROR); send_error(net, ER_UNKNOWN_COM_ERROR);
break; break;
} }
if (check_user(thd, COM_CHANGE_USER, user, passwd, db,0)) if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0))
{ // Restore old user { // Restore old user
x_free(thd->user); x_free(thd->user);
x_free(thd->db); x_free(thd->db);
...@@ -652,6 +779,7 @@ bool do_command(THD *thd) ...@@ -652,6 +779,7 @@ bool do_command(THD *thd)
thd->priv_user=save_priv_user; thd->priv_user=save_priv_user;
break; break;
} }
decrease_user_connections (save_user, thd->host);
x_free((gptr) save_db); x_free((gptr) save_db);
x_free((gptr) save_user); x_free((gptr) save_user);
thd->password=test(passwd[0]); thd->password=test(passwd[0]);
......
...@@ -352,6 +352,10 @@ sweepstakes if you report the bug"; ...@@ -352,6 +352,10 @@ sweepstakes if you report the bug";
case LOG_READ_BOGUS: case LOG_READ_BOGUS:
errmsg = "bogus data in log event"; errmsg = "bogus data in log event";
break; break;
case LOG_READ_TOO_LARGE:
errmsg = "log event entry exceeded max_allowed_packet -\
increase max_allowed_packet on master";
break;
case LOG_READ_IO: case LOG_READ_IO:
errmsg = "I/O error reading log event"; errmsg = "I/O error reading log event";
break; break;
......
...@@ -33,13 +33,13 @@ ...@@ -33,13 +33,13 @@
static char from_buff[100],to_buff[100]; static char from_buff[100],to_buff[100];
static my_string from,to; static my_string from,to;
static int errors,tests; static int errors,tests;
static int test_strarg(char *name,...); static int test_strarg(const char *name,...);
static void init_strings (void); /* Init from and to */ static void init_strings (void); /* Init from and to */
void test_arg (my_string message,long func_value,long value); void test_arg (const char *message,long func_value,long value);
int compare_buff (my_string message,my_string b1,my_string b2,int length, int compare_buff(const char *message,my_string b1,my_string b2,int length,
pchar fill, pchar prefill); pchar fill, pchar prefill);
int my_test(int a) static int my_test(int a)
{ {
return a ? 1 : 0; return a ? 1 : 0;
} }
...@@ -116,6 +116,14 @@ int main(void) ...@@ -116,6 +116,14 @@ int main(void)
test_strarg("strxmov(to,from,\"!!\",NullS)",strxmov(to,from,"!!",NullS),to+F_LEN+2,F_LEN,F_CHAR,2,'!',0,0,0); test_strarg("strxmov(to,from,\"!!\",NullS)",strxmov(to,from,"!!",NullS),to+F_LEN+2,F_LEN,F_CHAR,2,'!',0,0,0);
test_strarg("strxmov(to,NullS)",strxmov(to,NullS),to,1,0,0,0); test_strarg("strxmov(to,NullS)",strxmov(to,NullS),to,1,0,0,0);
test_strarg("strxmov(to,from,from,from,from,from,'!!',from,NullS)",strxmov(to,from,from,from,from,from,"!!",from,NullS),to+F_LEN*6+2,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,2,'!',F_LEN,F_CHAR,1,0,0,0); test_strarg("strxmov(to,from,from,from,from,from,'!!',from,NullS)",strxmov(to,from,from,from,from,from,"!!",from,NullS),to+F_LEN*6+2,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,2,'!',F_LEN,F_CHAR,1,0,0,0);
test_strarg("strxnmov(to,100,from,\"!!\",NullS)",strxnmov(to,100,from,"!!",NullS),to+F_LEN+2,F_LEN,F_CHAR,2,'!',0,0,0);
test_strarg("strxnmov(to,2,NullS)",strxnmov(to,2,NullS),to,1,0,0,0);
test_strarg("strxnmov(to,100,from,from,from,from,from,'!!',from,NullS)",strxnmov(to,100,from,from,from,from,from,"!!",from,NullS),to+F_LEN*6+2,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,F_LEN,F_CHAR,2,'!',F_LEN,F_CHAR,1,0,0,0);
test_strarg("strxnmov(to,2,\"!!!\",NullS)",strxnmov(to,2,"!!!",NullS),to+2,2,'!',0,0,0);
test_strarg("strxnmov(to,2,\"!!\",NullS)",strxnmov(to,2,"!!","xx",NullS),to+2,2,'!',0,0,0);
test_strarg("strxnmov(to,2,\"!\",\"x\",\"y\",NullS)",strxnmov(to,2,"!","x","y",NullS),to+2,1,'!',1,'x',0,0,0);
test_strarg("bchange(to,2,from,4,6)",(bchange(to,2,from,4,6),0L),INT_MAX32, test_strarg("bchange(to,2,from,4,6)",(bchange(to,2,from,4,6),0L),INT_MAX32,
4,F_CHAR,2,T_CHAR,0,0); 4,F_CHAR,2,T_CHAR,0,0);
...@@ -156,7 +164,7 @@ void init_strings(void) ...@@ -156,7 +164,7 @@ void init_strings(void)
/* Test that function return rigth value */ /* Test that function return rigth value */
void test_arg(my_string message, long int func_value, long int value) void test_arg(const char *message, long int func_value, long int value)
{ {
tests++; tests++;
printf("testing '%s'\n",message); printf("testing '%s'\n",message);
...@@ -169,7 +177,7 @@ void test_arg(my_string message, long int func_value, long int value) ...@@ -169,7 +177,7 @@ void test_arg(my_string message, long int func_value, long int value)
/* Test function return value and from and to arrays */ /* Test function return value and from and to arrays */
static int test_strarg(char *message,...) static int test_strarg(const char *message,...)
{ {
long func_value,value; long func_value,value;
int error,length; int error,length;
...@@ -223,7 +231,7 @@ static int test_strarg(char *message,...) ...@@ -223,7 +231,7 @@ static int test_strarg(char *message,...)
/* test if function made right value */ /* test if function made right value */
int compare_buff(my_string message, my_string b1, my_string b2, int length, int compare_buff(const char *message, my_string b1, my_string b2, int length,
pchar fill, pchar prefill) pchar fill, pchar prefill)
{ {
int i,error=0; int i,error=0;
...@@ -256,6 +264,8 @@ int compare_buff(my_string message, my_string b1, my_string b2, int length, ...@@ -256,6 +264,8 @@ int compare_buff(my_string message, my_string b1, my_string b2, int length,
/* These are here to be loaded and examined */ /* These are here to be loaded and examined */
extern void dummy_functions(void);
void dummy_functions(void) void dummy_functions(void)
{ {
VOID(memchr(from,'a',5)); VOID(memchr(from,'a',5));
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
and NOT to use 0, as on some machines 0 is not the same size as a and NOT to use 0, as on some machines 0 is not the same size as a
character pointer, or not the same bit pattern as NullS. character pointer, or not the same bit pattern as NullS.
Note: strxnmov is like strnmov in that it always moves EXACTLY len Note: strxnmov is like strnmov in that it moves up to len
characters; dst will be padded on the right with NUL characters as characters; dst will be padded on the right with one NUL characters if
needed. strxncpy does the same. strxncat, like strncat, does NOT. needed.
*/ */
#include <global.h> #include <global.h>
...@@ -27,20 +27,22 @@ ...@@ -27,20 +27,22 @@
char *strxnmov(char *dst,uint len, const char *src, ...) char *strxnmov(char *dst,uint len, const char *src, ...)
{ {
va_list pvar; va_list pvar;
char *result; char *end_of_dst=dst+len;
va_start(pvar,src); va_start(pvar,src);
while (src != NullS) { while (src != NullS)
do if (len-- == 0) {
do
{ {
va_end(pvar); if (dst == end_of_dst)
return dst; goto end;
} }
while ((*dst++ = *src++) != 0); while ((*dst++ = *src++));
dst--; dst--;
src = va_arg(pvar, char *); src = va_arg(pvar, char *);
} }
for (result= dst; len-- != 0; *dst++ = 0) ; *dst=0;
end:
va_end(pvar); va_end(pvar);
return result; return dst;
} }
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